├── .gitignore ├── src ├── transforms │ ├── .git-ignore │ ├── hover-box-include.js │ ├── byline.js │ ├── toc.js │ ├── include.js │ ├── citation-list.js │ ├── reorder.js │ ├── markdown.js │ ├── banner.js │ ├── html.js │ ├── footnote.js │ ├── code.js │ ├── front-matter.js │ ├── mathematics.js │ ├── optional-components.js │ ├── hover-box.txt │ ├── polyfills.js │ ├── typeset.js │ ├── generate-crossref.js │ └── meta.js ├── assets │ ├── distill-favicon.png │ ├── distill-logo.svg │ ├── distill-favicon.svg │ └── distill-favicon.base64 ├── helpers │ ├── domContentLoaded.js │ ├── layout.js │ ├── bibtex.js │ ├── polyfills.js │ ├── citation.js │ └── katex-auto-render.js ├── components │ ├── d-title.js │ ├── d-references.js │ ├── d-abstract.js │ ├── d-article.js │ ├── d-appendix.js │ ├── d-byline.js │ ├── d-toc.js │ ├── d-citation-list.js │ ├── d-footnote-list.js │ ├── d-footnote.js │ ├── d-front-matter.js │ ├── d-code.js │ ├── d-bibliography.js │ ├── d-math.js │ ├── d-hover-box.js │ ├── d-interstitial.js │ ├── d-cite.js │ └── d-figure.js ├── styles │ ├── d-math.css │ ├── styles-print.css │ ├── styles.js │ ├── d-title.css │ ├── d-byline.css │ ├── styles-base.css │ ├── styles-layout.css │ └── d-article.css ├── distill-components │ ├── distill-footer.js │ ├── distill-header.js │ ├── distill-header-template.js │ ├── distill-footer-template.js │ └── distill-appendix.js ├── extractors │ ├── citations.js │ ├── front-matter.js │ └── bibliography.js ├── distill-transforms │ ├── distill-footer.js │ ├── distill-header.js │ └── distill-appendix.js ├── mixins │ ├── mutating.js │ ├── template.js │ └── properties.js ├── transforms.js ├── components.js └── controller.js ├── test ├── mocha.opts ├── helpers.js ├── scaffolds │ ├── usesV1.html │ └── usesV2.html └── template_v1.js ├── examples ├── momentum.png ├── bibliography.bib └── index.html ├── .npmignore ├── .editorconfig ├── AUTHORS ├── .travis.yml ├── .eslintrc.json ├── rollup.config.prod.js ├── README.md ├── rollup.config.dev.js ├── CONTRIBUTING.md ├── bin └── render.js ├── package.json └── rollup.config.common.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /src/transforms/.git-ignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r jsdom-global/register 2 | -------------------------------------------------------------------------------- /examples/momentum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/distillpub/template/HEAD/examples/momentum.png -------------------------------------------------------------------------------- /src/assets/distill-favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/distillpub/template/HEAD/src/assets/distill-favicon.png -------------------------------------------------------------------------------- /src/helpers/domContentLoaded.js: -------------------------------------------------------------------------------- 1 | export function domContentLoaded() { 2 | return ['interactive', 'complete'].indexOf(document.readyState) !== -1; 3 | } 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | build 3 | .editorconfig 4 | .eslintrc.json 5 | .gitignore 6 | .travis.yml 7 | rollup.config.dev.js 8 | rollup.config.js 9 | yarn-error.log 10 | -------------------------------------------------------------------------------- /src/assets/distill-logo.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = spaces 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.{json,yml}] 12 | indent_size = 2 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of The Distill Template authors for copyright purposes. 2 | # 3 | # This does not necessarily list everyone who has contributed code, since in 4 | # some cases, their employer may be the copyright holder. To see the full list 5 | # of contributors, see the revision history in source control. 6 | Google LLC 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" # latest version 4 | cache: 5 | directories: 6 | - node_modules 7 | script: 8 | - npm run build 9 | - npm test 10 | deploy: 11 | provider: releases 12 | api_key: $GITHUB_OAUTH_TOKEN 13 | file_glob: true 14 | file: dist/* 15 | skip_cleanup: true 16 | overwrite: true 17 | on: 18 | tags: true 19 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "node": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "sourceType": "module" 10 | }, 11 | "rules": { 12 | "no-unused-vars": ["warn", { "vars": "all", "args": "after-used" }], 13 | "no-console": ["off", { "allow": ["warn", "error"] } ], 14 | "no-empty": ["error", { "allowEmptyCatch": true }], 15 | "indent": [ "warn", 2 ], 16 | "linebreak-style": [ "error", "unix" ], 17 | "quotes": [ "warn", "single" ], 18 | "semi": [ "warn", "always" ], 19 | "no-extra-semi": [ "warn" ], 20 | "no-debugger": [ "warn" ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /rollup.config.prod.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import configs from "./rollup.config.common"; 16 | 17 | export default configs; 18 | -------------------------------------------------------------------------------- /test/helpers.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | function nodeListToArray(nodeList) { 16 | return Array.prototype.slice.call(nodeList); 17 | } 18 | -------------------------------------------------------------------------------- /src/components/d-title.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | export class Title extends HTMLElement { 16 | static get is() { return 'd-title'; } 17 | } 18 | -------------------------------------------------------------------------------- /src/assets/distill-favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /src/transforms/hover-box-include.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import code from './hover-box.txt'; 16 | 17 | export default function(dom) { 18 | let s = dom.createElement('script'); 19 | s.textContent = code; 20 | dom.querySelector('body').appendChild(s); 21 | } 22 | -------------------------------------------------------------------------------- /src/transforms/byline.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { bylineTemplate } from '../components/d-byline.js'; 16 | 17 | export default function(dom, data) { 18 | const byline = dom.querySelector('d-byline'); 19 | if (byline) { 20 | byline.innerHTML = bylineTemplate(data); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/scaffolds/usesV1.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/scaffolds/usesV2.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Distill Template 2 | 3 | This is the repository for the Distill web framework. 4 | 5 | ## Contributing 6 | 7 | 8 | To give feedback, report a bug, or request a feature, please open an issue. 9 | 10 | To contribute a change, [check out the contributing guide](CONTRIBUTING.md). 11 | 12 | ### Local Development 13 | 14 | First, run `npm install` to install all node modules required. Then, run `npm run dev` to start a watching build rollup server. To view the sample pages in the repo, you can run `npm run serve` as a separate process which starts a static server. `npm run build` will run a one-time build. 15 | 16 | 17 | ## Disclaimer & License 18 | 19 | _This project is research code. It is not an official product of Google or any other institution supporting Distill._ 20 | 21 | Copyright 2018, The Distill Template Authors. 22 | 23 | Licensed under the Apache License, Version 2.0 24 | 25 | See the [full license](LICENSE). 26 | -------------------------------------------------------------------------------- /src/styles/d-math.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The Distill Template Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | span.katex-display { 18 | text-align: left; 19 | padding: 8px 0 8px 0; 20 | margin: 0.5em 0 0.5em 1em; 21 | } 22 | 23 | span.katex { 24 | -webkit-font-smoothing: antialiased; 25 | color: rgba(0, 0, 0, 0.8); 26 | font-size: 1.18em; 27 | } 28 | -------------------------------------------------------------------------------- /src/components/d-references.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { Template } from '../mixins/template'; 16 | 17 | const T = Template('d-references', ` 18 | 23 | `, false); 24 | 25 | export class References extends T(HTMLElement) { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/distill-components/distill-footer.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { Template } from '../mixins/template'; 16 | 17 | import {footerTemplate} from './distill-footer-template'; 18 | 19 | const T = Template('distill-footer', footerTemplate); 20 | 21 | export class DistillFooter extends T(HTMLElement) { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/distill-components/distill-header.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { Template } from '../mixins/template'; 16 | 17 | import {headerTemplate} from './distill-header-template'; 18 | 19 | const T = Template('distill-header', headerTemplate, false); 20 | 21 | export class DistillHeader extends T(HTMLElement) { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/extractors/citations.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { collect_citations } from '../helpers/citation.js'; 16 | 17 | export default function(dom, data) { 18 | const citations = new Set(data.citations); 19 | const newCitations = collect_citations(dom); 20 | for (const citation of newCitations) { 21 | citations.add(citation); 22 | } 23 | data.citations = Array.from(citations); 24 | } 25 | -------------------------------------------------------------------------------- /src/transforms/toc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { renderTOC } from '../components/d-toc'; 16 | 17 | export default function(dom) { 18 | const article = dom.querySelector('d-article'); 19 | const toc = dom.querySelector('d-toc'); 20 | if (toc) { 21 | const headings = article.querySelectorAll('h2, h3'); 22 | renderTOC(toc, headings); 23 | toc.setAttribute('prerendered', 'true'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/distill-transforms/distill-footer.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { footerTemplate } from '../distill-components/distill-footer-template'; 16 | 17 | export default function(dom) { 18 | const footerTag = dom.querySelector('distill-footer'); 19 | if(!footerTag) { 20 | const footer = dom.createElement('distill-footer'); 21 | footer.innerHTML = footerTemplate; 22 | const body = dom.querySelector('body'); 23 | body.appendChild(footer); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/extractors/front-matter.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { parseFrontmatter } from '../components/d-front-matter'; 16 | import { mergeFromYMLFrontmatter } from '../front-matter.js'; 17 | 18 | export default function(dom, data) { 19 | const frontMatterTag = dom.querySelector('d-front-matter'); 20 | if (!frontMatterTag) { 21 | console.warn('No front matter tag found!'); 22 | return; 23 | } 24 | const extractedData = parseFrontmatter(frontMatterTag); 25 | mergeFromYMLFrontmatter(data, extractedData); 26 | } 27 | -------------------------------------------------------------------------------- /rollup.config.dev.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import configs from "./rollup.config.common"; 16 | import serve from "rollup-plugin-serve"; 17 | 18 | const [componentsConfig, transformsConfig] = configs; 19 | 20 | componentsConfig.plugins.push( 21 | serve({ 22 | open: true, 23 | openPage: "/index.html", 24 | contentBase: ["dist", "examples"], 25 | headers: { 26 | "Access-Control-Allow-Origin": "*" 27 | }, 28 | port: 8088 29 | }) 30 | ); 31 | 32 | export default [componentsConfig, transformsConfig]; 33 | -------------------------------------------------------------------------------- /src/distill-transforms/distill-header.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | import { headerTemplate } from '../distill-components/distill-header-template'; 17 | 18 | export default function(dom, data) { 19 | const headerTag = dom.querySelector('distill-header'); 20 | if (!headerTag) { 21 | const header = dom.createElement('distill-header'); 22 | header.innerHTML = headerTemplate; 23 | header.setAttribute('distill-prerendered', ""); 24 | const body = dom.querySelector('body'); 25 | body.insertBefore(header, body.firstChild); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/transforms/include.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import fetch from 'fetch'; 16 | let fetchUrl = fetch.fetchUrl; 17 | 18 | export default function(dom, data) { 19 | 20 | var includeTags = [].slice.apply(dom.querySelectorAll('dt-include')); 21 | 22 | includeTags.forEach(el => { 23 | let src = el.getAttribute('src'); 24 | fetchUrl(src, (err, meta, body) => { 25 | console.log(err, meta, body); 26 | el.innerHTML = body.toString(); 27 | }); 28 | }); 29 | data.bibliography = bibliography; 30 | data.citations = citations; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/transforms/citation-list.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Distill Template Authors 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import { renderCitationList } from '../components/d-citation-list'; // (element, entries) 16 | 17 | export default function(dom, data) { 18 | const citationListTag = dom.querySelector('d-citation-list'); 19 | if (citationListTag) { 20 | const entries = new Map(data.citations.map( citationKey => { 21 | return [citationKey, data.bibliography.get(citationKey)]; 22 | })); 23 | renderCitationList(citationListTag, entries, dom); 24 | citationListTag.setAttribute('distill-prerendered', 'true'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to tag. We found the following text: ' + text);
34 | const wrapper = document.createElement('span');
35 | wrapper.innerHTML = addedNode.nodeValue;
36 | addedNode.parentNode.insertBefore(wrapper, addedNode);
37 | addedNode.parentNode.removeChild(addedNode);
38 | }
39 | } break;
40 | }
41 | }
42 | }
43 | }).observe(this, {childList: true});
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/components/d-appendix.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import { Template } from '../mixins/template';
16 |
17 | const T = Template('d-appendix', `
18 |
75 |
76 | `, false);
77 |
78 | export class Appendix extends T(HTMLElement) {
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/styles/d-byline.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The Distill Template Authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | d-byline {
18 | contain: style;
19 | overflow: hidden;
20 | border-top: 1px solid rgba(0, 0, 0, 0.1);
21 | font-size: 0.8rem;
22 | line-height: 1.8em;
23 | padding: 1.5rem 0;
24 | min-height: 1.8em;
25 | }
26 |
27 |
28 | d-byline .byline {
29 | grid-template-columns: 1fr 1fr;
30 | grid-column: text;
31 | }
32 |
33 | @media(min-width: 768px) {
34 | d-byline .byline {
35 | grid-template-columns: 1fr 1fr 1fr 1fr;
36 | }
37 | }
38 |
39 | d-byline .authors-affiliations {
40 | grid-column-end: span 2;
41 | grid-template-columns: 1fr 1fr;
42 | margin-bottom: 1em;
43 | }
44 |
45 | @media(min-width: 768px) {
46 | d-byline .authors-affiliations {
47 | margin-bottom: 0;
48 | }
49 | }
50 |
51 | d-byline h3 {
52 | font-size: 0.6rem;
53 | font-weight: 400;
54 | color: rgba(0, 0, 0, 0.5);
55 | margin: 0;
56 | text-transform: uppercase;
57 | }
58 |
59 | d-byline p {
60 | margin: 0;
61 | }
62 |
63 | d-byline a,
64 | d-article d-byline a {
65 | color: rgba(0, 0, 0, 0.8);
66 | text-decoration: none;
67 | border-bottom: none;
68 | }
69 |
70 | d-article d-byline a:hover {
71 | text-decoration: underline;
72 | border-bottom: none;
73 | }
74 |
75 | d-byline p.author {
76 | font-weight: 500;
77 | }
78 |
79 | d-byline .affiliations {
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/src/helpers/bibtex.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import bibtexParse from 'bibtex-parse-js';
16 |
17 | function normalizeTag(string) {
18 | return string
19 | .replace(/[\t\n ]+/g, ' ')
20 | .replace(/{\\["^`.'acu~Hvs]( )?([a-zA-Z])}/g, (full, x, char) => char)
21 | .replace(/{\\([a-zA-Z])}/g, (full, char) => char)
22 | .replace(/[{}]/gi,''); // Replace curly braces forcing plaintext in latex.
23 | }
24 |
25 | export function parseBibtex(bibtex) {
26 | const bibliography = new Map();
27 | const parsedEntries = bibtexParse.toJSON(bibtex);
28 | for (const entry of parsedEntries) {
29 | // normalize tags; note entryTags is an object, not Map
30 | for (const [key, value] of Object.entries(entry.entryTags)) {
31 | entry.entryTags[key.toLowerCase()] = normalizeTag(value);
32 | }
33 | entry.entryTags.type = entry.entryType;
34 | // add to bibliography
35 | bibliography.set(entry.citationKey, entry.entryTags);
36 | }
37 | return bibliography;
38 | }
39 |
40 | export function serializeFrontmatterToBibtex(frontMatter) {
41 | return `@article{${frontMatter.slug},
42 | author = {${frontMatter.bibtexAuthors}},
43 | title = {${frontMatter.title}},
44 | journal = {${frontMatter.journal.title}},
45 | year = {${frontMatter.publishedYear}},
46 | note = {${frontMatter.url}},
47 | doi = {${frontMatter.doi}}
48 | }`;
49 | }
50 |
--------------------------------------------------------------------------------
/src/transforms/front-matter.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import ymlParse from 'js-yaml';
16 |
17 | export default function(dom, data) {
18 | let localData = {};
19 | let el = dom.querySelector('script[type="text/front-matter"]');
20 | if (el) {
21 | let text = el.textContent;
22 | localData = ymlParse.safeLoad(text);
23 | }
24 |
25 | data.title = localData.title ? localData.title : 'Untitled';
26 | data.description = localData.description ? localData.description : 'No description.';
27 |
28 | data.authors = localData.authors ? localData.authors : [];
29 |
30 | data.authors = data.authors.map((author, i) =>{
31 | let a = {};
32 | let name = Object.keys(author)[0];
33 | if ((typeof author) === 'string') {
34 | name = author;
35 | } else {
36 | a.personalURL = author[name];
37 | }
38 | let names = name.split(' ');
39 | a.name = name;
40 | a.firstName = names.slice(0, names.length - 1).join(' ');
41 | a.lastName = names[names.length -1];
42 | if(localData.affiliations[i]) {
43 | let affiliation = Object.keys(localData.affiliations[i])[0];
44 | if ((typeof localData.affiliations[i]) === 'string') {
45 | affiliation = localData.affiliations[i];
46 | } else {
47 | a.affiliationURL = localData.affiliations[i][affiliation];
48 | }
49 | a.affiliation = affiliation;
50 | }
51 | return a;
52 | });
53 |
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/transforms/mathematics.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import katex from 'katex';
16 | import { renderMathInElement } from '../helpers/katex-auto-render';
17 |
18 | export default function(dom, data) {
19 | let needsCSS = false;
20 | const body = dom.querySelector('body');
21 |
22 | if (!body) {
23 | console.warn("No body tag found!");
24 | return;
25 | }
26 |
27 | if (data.katex && data.katex.delimiters) {
28 | global.document = dom;
29 | renderMathInElement(body, data.katex);
30 | }
31 |
32 | // render d-math tags
33 | const mathTags = body.querySelectorAll('d-math');
34 | if (mathTags.length > 0) {
35 | needsCSS = true;
36 | console.warn(`Prerendering ${mathTags.length} math tags...`);
37 | for (const mathTag of mathTags) {
38 | const localOptions = { displayMode: mathTag.hasAttribute('block') };
39 | const options = Object.assign(localOptions, data.katex);
40 | const html = katex.renderToString(mathTag.textContent, options);
41 | const container = dom.createElement('span');
42 | container.innerHTML = html;
43 | mathTag.parentElement.insertBefore(container, mathTag);
44 | mathTag.parentElement.removeChild(mathTag);
45 | }
46 | }
47 |
48 | if (needsCSS) {
49 | const katexCSSTag = '';
50 | dom.head.insertAdjacentHTML('beforeend', katexCSSTag);
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/bin/render.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // Copyright 2018 The Distill Template Authors
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 |
17 | const path = require('path');
18 | const fs = require('fs');
19 | const program = require('commander');
20 | const jsdom = require('jsdom');
21 | const { JSDOM } = jsdom;
22 | const transforms = require('../dist/transforms.v2.js');
23 |
24 | program
25 | .version('1.0.0')
26 | .description('Pre-renders distill articles for publication.')
27 | .usage('-i `;
52 | if (frontMatter.githubCompareUpdatesUrl) {
53 | html += `View all changes to this article since it was first published.`;
54 | }
55 | html += `
56 | If you see mistakes or want to suggest changes, please create an issue on GitHub. Diagrams and text are licensed under Creative Commons Attribution CC-BY 4.0 with the source available on GitHub, unless noted otherwise. The figures that have been reused from other sources don’t fall under this license and can be recognized by a note in their caption: “Figure from …”. For attribution in academic contexts, please cite this work as BibTeX citation We often think of Momentum Before diving in: if you haven’t encountered t-SNE before, here’s what you need to know about the math behind it.
70 | The goal is to take a set of points in a high-dimensional space and find a faithful representation of those points
71 | in a lower-dimensional space, typically the 2D plane. The algorithm is non-linear and adapts to the underlying
72 | data, performing different transformations on different regions. Those differences can be a major source of
73 | confusion. This is the first paragraph of the article. Test a long — dash -- here it is. Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two. Some flopping fins; for
76 | diving. Here's a test of an inline equation Math can also be quite involved:
91 | We can Some inline javascript: We also support python. And a table That's it for the example article! Some text describing who did what. Some text with links describing who reviewed the article.Table of contents
57 | `;
58 |
59 | for (const el of headings) {
60 | // should element be included in TOC?
61 | const isInTitle = el.parentElement.tagName == 'D-TITLE';
62 | const isException = el.getAttribute('no-toc');
63 | if (isInTitle || isException) continue;
64 | // create TOC entry
65 | const title = el.textContent;
66 | const link = '#' + el.getAttribute('id');
67 |
68 | let newLine = '
';
79 | element.innerHTML = ToC;
80 | }
81 |
--------------------------------------------------------------------------------
/src/components/d-citation-list.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import { bibliography_cite } from '../helpers/citation';
16 |
17 | const styles = `
18 | d-citation-list {
19 | contain: style;
20 | }
21 |
22 | d-citation-list .references {
23 | grid-column: text;
24 | }
25 |
26 | d-citation-list .references .title {
27 | font-weight: 500;
28 | }
29 | `;
30 |
31 | export function renderCitationList(element, entries, dom=document) {
32 | if (entries.size > 0) {
33 | element.style.display = '';
34 | let list = element.querySelector('.references');
35 | if (list) {
36 | list.innerHTML = '';
37 | } else {
38 | const stylesTag = dom.createElement('style');
39 | stylesTag.innerHTML = styles;
40 | element.appendChild(stylesTag);
41 |
42 | const heading = dom.createElement('h3');
43 | heading.id = 'references';
44 | heading.textContent = 'References';
45 | element.appendChild(heading);
46 |
47 | list = dom.createElement('ol');
48 | list.id = 'references-list';
49 | list.className = 'references';
50 | element.appendChild(list);
51 | }
52 |
53 | for (const [key, entry] of entries) {
54 | const listItem = dom.createElement('li');
55 | listItem.id = key;
56 | listItem.innerHTML = bibliography_cite(entry);
57 | list.appendChild(listItem);
58 | }
59 | } else {
60 | element.style.display = 'none';
61 | }
62 | }
63 |
64 | export class CitationList extends HTMLElement {
65 |
66 | static get is() { return 'd-citation-list'; }
67 |
68 | connectedCallback() {
69 | if (!this.hasAttribute('distill-prerendered')) {
70 | this.style.display = 'none';
71 | }
72 | }
73 |
74 | set citations(citations) {
75 | renderCitationList(this, citations);
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/components/d-footnote-list.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import { Template } from '../mixins/template';
16 |
17 | const T = Template('d-footnote-list', `
18 |
34 |
35 | ' + newLine + '
';
71 | } else {
72 | newLine += '
';
73 | }
74 | ToC += newLine;
75 |
76 | }
77 |
78 | ToC += 'Footnotes
36 |
37 | `, false);
38 |
39 | export class FootnoteList extends T(HTMLElement) {
40 |
41 | connectedCallback() {
42 | super.connectedCallback();
43 |
44 | this.list = this.root.querySelector('ol');
45 | // footnotes list is initially hidden
46 | this.root.style.display = 'none';
47 | // look through document and register existing footnotes
48 | // Store.subscribeTo('footnotes', (footnote) => {
49 | // this.renderFootnote(footnote);
50 | // });
51 | }
52 |
53 | // TODO: could optimize this to accept individual footnotes?
54 | set footnotes(footnotes) {
55 | this.list.innerHTML = '';
56 | if (footnotes.length) {
57 | // ensure footnote list is visible
58 | this.root.style.display = '';
59 |
60 | for (const footnote of footnotes) {
61 | // construct and append list item to show footnote
62 | const listItem = document.createElement('li');
63 | listItem.id = footnote.id + '-listing';
64 | listItem.innerHTML = footnote.innerHTML;
65 |
66 | const backlink = document.createElement('a');
67 | backlink.setAttribute('class', 'footnote-backlink');
68 | backlink.textContent = '[↩]';
69 | backlink.href = '#' + footnote.id;
70 |
71 | listItem.appendChild(backlink);
72 | this.list.appendChild(listItem);
73 | }
74 | } else {
75 | // ensure footnote list is invisible
76 | this.root.style.display = 'none';
77 | }
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/components/d-footnote.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import { Template } from '../mixins/template.js';
16 |
17 | const T = Template('d-footnote', `
18 |
46 |
47 |
52 |
53 | `);
54 |
55 | export class Code extends Mutating(T(HTMLElement)) {
56 |
57 | renderContent() {
58 |
59 | // check if language can be highlighted
60 | this.languageName = this.getAttribute('language');
61 | if (!this.languageName) {
62 | console.warn('You need to provide a language attribute to your Updates and Corrections
51 | Reuse
64 | Citation
71 | ${frontMatter.concatenatedAuthors}, "${frontMatter.title}", Distill, ${frontMatter.publishedYear}.
73 | ${serializeFrontmatterToBibtex(frontMatter)}
75 | `;
76 | }
77 |
78 | return html;
79 | }
80 |
81 | export class DistillAppendix extends HTMLElement {
82 |
83 | static get is() { return 'distill-appendix'; }
84 |
85 | set frontMatter(frontMatter) {
86 | this.innerHTML = appendixTemplate(frontMatter);
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/components/d-bibliography.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import { parseBibtex } from '../helpers/bibtex';
16 |
17 | export function parseBibliography(element) {
18 | const scriptTag = element.firstElementChild;
19 | if (scriptTag && scriptTag.tagName === 'SCRIPT') {
20 | if (scriptTag.type == 'text/bibtex') {
21 | const bibtex = element.firstElementChild.textContent;
22 | return parseBibtex(bibtex);
23 | } else if (scriptTag.type == 'text/json') {
24 | return new Map(JSON.parse(scriptTag.textContent));
25 | } else {
26 | console.warn('Unsupported bibliography script tag type: ' + scriptTag.type);
27 | }
28 | } else {
29 | console.warn('Bibliography did not have any script tag.');
30 | }
31 | }
32 |
33 | export class Bibliography extends HTMLElement {
34 |
35 | static get is() { return 'd-bibliography'; }
36 |
37 | constructor() {
38 | super();
39 |
40 | // set up mutation observer
41 | const options = {childList: true, characterData: true, subtree: true};
42 | const observer = new MutationObserver( (entries) => {
43 | for (const entry of entries) {
44 | if (entry.target.nodeName === 'SCRIPT' || entry.type === 'characterData') {
45 | this.parseIfPossible();
46 | }
47 | }
48 | });
49 | observer.observe(this, options);
50 | }
51 |
52 | connectedCallback() {
53 | requestAnimationFrame(() => {
54 | this.parseIfPossible();
55 | });
56 | }
57 |
58 | parseIfPossible() {
59 | const scriptTag = this.querySelector('script');
60 | if (!scriptTag) return;
61 | if (scriptTag.type == 'text/bibtex') {
62 | const newBibtex = scriptTag.textContent;
63 | if (this.bibtex !== newBibtex) {
64 | this.bibtex = newBibtex;
65 | const bibliography = parseBibtex(this.bibtex);
66 | this.notify(bibliography);
67 | }
68 | } else if (scriptTag.type == 'text/json') {
69 | const bibliography = new Map(JSON.parse(scriptTag.textContent));
70 | this.notify(bibliography);
71 | } else {
72 | console.warn('Unsupported bibliography script tag type: ' + scriptTag.type);
73 | }
74 | }
75 |
76 | notify(bibliography) {
77 | const options = { detail: bibliography, bubbles: true };
78 | const event = new CustomEvent('onBibliographyChanged', options);
79 | this.dispatchEvent(event);
80 | }
81 |
82 | /* observe 'src' attribute */
83 |
84 | static get observedAttributes() {
85 | return ['src'];
86 | }
87 |
88 | receivedBibtex(event) {
89 | const bibliography = parseBibtex(event.target.response);
90 | this.notify(bibliography);
91 | }
92 |
93 | attributeChangedCallback(name, oldValue, newValue) {
94 | var oReq = new XMLHttpRequest();
95 | oReq.onload = (e) => this.receivedBibtex(e);
96 | oReq.onerror = () => console.warn(`Could not load Bibtex! (tried ${newValue})`);
97 | oReq.responseType = 'text';
98 | oReq.open('GET', newValue, true);
99 | oReq.send();
100 | }
101 |
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/src/transforms/hover-box.txt:
--------------------------------------------------------------------------------
1 | // DistillHoverBox
2 | //=====================================
3 |
4 | function DistillHoverBox(key, pos){
5 |
6 | if (!(key in DistillHoverBox.contentMap)){
7 | console.error("No DistillHoverBox content registered for key", key);
8 | }
9 | if (key in DistillHoverBox.liveBoxes) {
10 | console.error("There already exists a DistillHoverBox for key", key);
11 | } else {
12 | for (var k in DistillHoverBox.liveBoxes)
13 | DistillHoverBox.liveBoxes[k].remove();
14 | DistillHoverBox.liveBoxes[key] = this;
15 | }
16 | this.key = key;
17 |
18 | var pretty = window.innerWidth > 600;
19 |
20 | var padding = pretty? 18 : 12;
21 | var outer_padding = pretty ? 18 : 0;
22 | var bbox = document.querySelector("body").getBoundingClientRect();
23 | var left = pos[0] - bbox.left, top = pos[1] - bbox.top;
24 | var width = Math.min(window.innerWidth-2*outer_padding, 648);
25 | left = Math.min(left, window.innerWidth-width-outer_padding);
26 | width = width - 2*padding;
27 |
28 | var str = `
169 | ${entries
170 | .map(hover_cite)
171 | .map(html => `
`;
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/src/components.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import { Controller } from './controller';
16 | import { domContentLoaded } from './helpers/domContentLoaded.js';
17 |
18 | /* Transforms */
19 | import { makeStyleTag } from './styles/styles';
20 | import { Polyfills } from './helpers/polyfills';
21 |
22 | /* Components */
23 | import { Abstract } from './components/d-abstract';
24 | import { Appendix } from './components/d-appendix';
25 | import { Article } from './components/d-article';
26 | import { Bibliography } from './components/d-bibliography';
27 | import { Byline } from './components/d-byline';
28 | import { Cite } from './components/d-cite';
29 | import { CitationList } from './components/d-citation-list';
30 | import { Code } from './components/d-code';
31 | import { Footnote } from './components/d-footnote';
32 | import { FootnoteList } from './components/d-footnote-list';
33 | import { FrontMatter } from './components/d-front-matter';
34 | import { HoverBox } from './components/d-hover-box';
35 | import { Title } from './components/d-title';
36 | import { DMath } from './components/d-math';
37 | import { References } from './components/d-references';
38 | import { TOC } from './components/d-toc';
39 | import { Figure } from './components/d-figure';
40 | import { Interstitial } from './components/d-interstitial';
41 | import { Slider } from './ui/d-slider';
42 |
43 | /* Distill website specific components */
44 | import { DistillHeader } from './distill-components/distill-header';
45 | import { DistillAppendix } from './distill-components/distill-appendix';
46 | import { DistillFooter } from './distill-components/distill-footer';
47 |
48 | let templateIsLoading = false;
49 | let runlevel = 0;
50 | const initialize = function() {
51 | if (window.distill.runlevel < 1) {
52 | throw new Error("Insufficient Runlevel for Distill Template!");
53 | }
54 |
55 | /* 1. Flag that we're being loaded */
56 | if ("distill" in window && window.distill.templateIsLoading) {
57 | throw new Error(
58 | "Runlevel 1: Distill Template is getting loaded more than once, aborting!"
59 | );
60 | } else {
61 | window.distill.templateIsLoading = true;
62 | console.debug("Runlevel 1: Distill Template has started loading.");
63 | }
64 |
65 | /* 2. Add styles if they weren't added during prerendering */
66 | makeStyleTag(document);
67 | console.debug("Runlevel 1: Static Distill styles have been added.");
68 | console.debug("Runlevel 1->2.");
69 | window.distill.runlevel += 1;
70 |
71 | /* 3. Register Controller listener functions */
72 | /* Needs to happen before components to their connected callbacks have a controller to talk to. */
73 | for (const [functionName, callback] of Object.entries(Controller.listeners)) {
74 | if (typeof callback === "function") {
75 | document.addEventListener(functionName, callback);
76 | } else {
77 | console.error("Runlevel 2: Controller listeners need to be functions!");
78 | }
79 | }
80 | console.debug("Runlevel 2: We can now listen to controller events.");
81 | console.debug("Runlevel 2->3.");
82 | window.distill.runlevel += 1;
83 |
84 | /* 4. Register components */
85 | const components = [
86 | Abstract, Appendix, Article, Bibliography, Byline, Cite, CitationList, Code,
87 | Footnote, FootnoteList, FrontMatter, HoverBox, Title, DMath, References, TOC, Figure,
88 | Slider, Interstitial
89 | ];
90 |
91 | const distillComponents = [DistillHeader, DistillAppendix, DistillFooter];
92 |
93 | if (window.distill.runlevel < 2) {
94 | throw new Error("Insufficient Runlevel for adding custom elements!");
95 | }
96 | const allComponents = components.concat(distillComponents);
97 | for (const component of allComponents) {
98 | console.debug("Runlevel 2: Registering custom element: " + component.is);
99 | customElements.define(component.is, component);
100 | }
101 |
102 | console.debug(
103 | "Runlevel 3: Distill Template finished registering custom elements."
104 | );
105 | console.debug("Runlevel 3->4.");
106 | window.distill.runlevel += 1;
107 |
108 | // If template was added after DOMContentLoaded we may have missed that event.
109 | // Controller will check for that case, so trigger the event explicitly:
110 | if (domContentLoaded()) {
111 | Controller.listeners.DOMContentLoaded();
112 | }
113 |
114 | console.debug("Runlevel 4: Distill Template initialisation complete.");
115 | window.distill.templateIsLoading = false;
116 | window.distill.templateHasLoaded = true;
117 | };
118 |
119 | window.distill = { runlevel, initialize, templateIsLoading };
120 |
121 | /* 0. Check browser feature support; synchronously polyfill if needed */
122 | if (Polyfills.browserSupportsAllFeatures()) {
123 | console.debug("Runlevel 0: No need for polyfills.");
124 | console.debug("Runlevel 0->1.");
125 | window.distill.runlevel += 1;
126 | window.distill.initialize();
127 | } else {
128 | console.debug("Runlevel 0: Distill Template is loading polyfills.");
129 | Polyfills.load(window.distill.initialize);
130 | }
131 |
--------------------------------------------------------------------------------
/src/styles/d-article.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The Distill Template Authors
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | d-article {
18 | contain: layout style;
19 | overflow-x: hidden;
20 | border-top: 1px solid rgba(0, 0, 0, 0.1);
21 | padding-top: 2rem;
22 | color: rgba(0, 0, 0, 0.8);
23 | }
24 |
25 | d-article > * {
26 | grid-column: text;
27 | }
28 |
29 | @media(min-width: 768px) {
30 | d-article {
31 | font-size: 16px;
32 | }
33 | }
34 |
35 | @media(min-width: 1024px) {
36 | d-article {
37 | font-size: 1.06rem;
38 | line-height: 1.7em;
39 | }
40 | }
41 |
42 |
43 | /* H2 */
44 |
45 |
46 | d-article .marker {
47 | text-decoration: none;
48 | border: none;
49 | counter-reset: section;
50 | grid-column: kicker;
51 | line-height: 1.7em;
52 | }
53 |
54 | d-article .marker:hover {
55 | border: none;
56 | }
57 |
58 | d-article .marker span {
59 | padding: 0 3px 4px;
60 | border-bottom: 1px solid rgba(0, 0, 0, 0.2);
61 | position: relative;
62 | top: 4px;
63 | }
64 |
65 | d-article .marker:hover span {
66 | color: rgba(0, 0, 0, 0.7);
67 | border-bottom: 1px solid rgba(0, 0, 0, 0.7);
68 | }
69 |
70 | d-article h2 {
71 | font-weight: 600;
72 | font-size: 24px;
73 | line-height: 1.25em;
74 | margin: 2rem 0 1.5rem 0;
75 | border-bottom: 1px solid rgba(0, 0, 0, 0.1);
76 | padding-bottom: 1rem;
77 | }
78 |
79 | @media(min-width: 1024px) {
80 | d-article h2 {
81 | font-size: 36px;
82 | }
83 | }
84 |
85 | /* H3 */
86 |
87 | d-article h3 {
88 | font-weight: 700;
89 | font-size: 18px;
90 | line-height: 1.4em;
91 | margin-bottom: 1em;
92 | margin-top: 2em;
93 | }
94 |
95 | @media(min-width: 1024px) {
96 | d-article h3 {
97 | font-size: 20px;
98 | }
99 | }
100 |
101 | /* H4 */
102 |
103 | d-article h4 {
104 | font-weight: 600;
105 | text-transform: uppercase;
106 | font-size: 14px;
107 | line-height: 1.4em;
108 | }
109 |
110 | d-article a {
111 | color: inherit;
112 | }
113 |
114 | d-article p,
115 | d-article ul,
116 | d-article ol,
117 | d-article blockquote {
118 | margin-top: 0;
119 | margin-bottom: 1em;
120 | margin-left: 0;
121 | margin-right: 0;
122 | }
123 |
124 | d-article blockquote {
125 | border-left: 2px solid rgba(0, 0, 0, 0.2);
126 | padding-left: 2em;
127 | font-style: italic;
128 | color: rgba(0, 0, 0, 0.6);
129 | }
130 |
131 | d-article a {
132 | border-bottom: 1px solid rgba(0, 0, 0, 0.4);
133 | text-decoration: none;
134 | }
135 |
136 | d-article a:hover {
137 | border-bottom: 1px solid rgba(0, 0, 0, 0.8);
138 | }
139 |
140 | d-article .link {
141 | text-decoration: underline;
142 | cursor: pointer;
143 | }
144 |
145 | d-article ul,
146 | d-article ol {
147 | padding-left: 24px;
148 | }
149 |
150 | d-article li {
151 | margin-bottom: 1em;
152 | margin-left: 0;
153 | padding-left: 0;
154 | }
155 |
156 | d-article li:last-child {
157 | margin-bottom: 0;
158 | }
159 |
160 | d-article pre {
161 | font-size: 14px;
162 | margin-bottom: 20px;
163 | }
164 |
165 | d-article hr {
166 | grid-column: screen;
167 | width: 100%;
168 | border: none;
169 | border-bottom: 1px solid rgba(0, 0, 0, 0.1);
170 | margin-top: 60px;
171 | margin-bottom: 60px;
172 | }
173 |
174 | d-article section {
175 | margin-top: 60px;
176 | margin-bottom: 60px;
177 | }
178 |
179 | d-article span.equation-mimic {
180 | font-family: georgia;
181 | font-size: 115%;
182 | font-style: italic;
183 | }
184 |
185 | d-article > d-code,
186 | d-article section > d-code {
187 | display: block;
188 | }
189 |
190 | d-article > d-math[block],
191 | d-article section > d-math[block] {
192 | display: block;
193 | }
194 |
195 | @media (max-width: 768px) {
196 | d-article > d-code,
197 | d-article section > d-code,
198 | d-article > d-math[block],
199 | d-article section > d-math[block] {
200 | overflow-x: scroll;
201 | -ms-overflow-style: none; // IE 10+
202 | overflow: -moz-scrollbars-none; // Firefox
203 | }
204 |
205 | d-article > d-code::-webkit-scrollbar,
206 | d-article section > d-code::-webkit-scrollbar,
207 | d-article > d-math[block]::-webkit-scrollbar,
208 | d-article section > d-math[block]::-webkit-scrollbar {
209 | display: none; // Safari and Chrome
210 | }
211 | }
212 |
213 | d-article .citation {
214 | color: #668;
215 | cursor: pointer;
216 | }
217 |
218 | d-include {
219 | width: auto;
220 | display: block;
221 | }
222 |
223 | d-figure {
224 | contain: layout style;
225 | }
226 |
227 | /* KaTeX */
228 |
229 | .katex, .katex-prerendered {
230 | contain: style;
231 | display: inline-block;
232 | }
233 |
234 | /* Tables */
235 |
236 | d-article table {
237 | border-collapse: collapse;
238 | margin-bottom: 1.5rem;
239 | border-bottom: 1px solid rgba(0, 0, 0, 0.2);
240 | }
241 |
242 | d-article table th {
243 | border-bottom: 1px solid rgba(0, 0, 0, 0.2);
244 | }
245 |
246 | d-article table td {
247 | border-bottom: 1px solid rgba(0, 0, 0, 0.05);
248 | }
249 |
250 | d-article table tr:last-of-type td {
251 | border-bottom: none;
252 | }
253 |
254 | d-article table th,
255 | d-article table td {
256 | font-size: 15px;
257 | padding: 2px 8px;
258 | }
259 |
260 | d-article table tbody :first-child td {
261 | padding-top: 2px;
262 | }
263 |
--------------------------------------------------------------------------------
/src/transforms/generate-crossref.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | //import xml from "xml";
16 |
17 | export default function(data) {
18 |
19 |
20 | var date = data.publishedDate;
21 |
22 | var batch_timestamp = Math.floor(Date.now() / 1000);
23 | var batch_id = data.authors.length ? data.authors[0].lastName.toLowerCase().slice(0,20) : 'Anonymous';
24 | batch_id += '_' + date.getFullYear();
25 | batch_id += '_' + data.title.split(' ')[0].toLowerCase().slice(0,20) + '_' + batch_timestamp;
26 | // generate XML
27 | var crf_data =
28 | {doi_batch : [
29 |
30 | { _attr: {
31 | version: '4.3.7',
32 | xmlns: 'http://www.crossref.org/schema/4.3.7',
33 | 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
34 | 'xsi:schemaLocation': 'http://www.crossref.org/schema/4.3.7 http://www.crossref.org/schemas/crossref4.3.7.xsd',
35 | }},
36 |
37 | { head: [
38 | {doi_batch_id: batch_id},
39 | {timestamp: batch_timestamp},
40 | {depositor: [
41 | {depositor_name: data.journal.publisherName},
42 | {email_address: data.journal.publisherEmail},
43 | ]},
44 | {registrant: data.journal.publisherName},
45 | ]},
46 |
47 | {body: [
48 | {journal: [
49 |
50 | {journal_metadata: [
51 | {full_title: data.journal.full_title || data.journal.title},
52 | {abbrev_title: data.journal.abbrev_title || data.journal.title || data.journal.full_title},
53 | {issn: data.journal.issn},
54 | {doi_data: [
55 | {doi: data.journal.doi},
56 | {resource: data.journal.url},
57 | ]},
58 | ]},
59 |
60 | {journal_issue: [
61 | {publication_date: [
62 | {month: date.getMonth()+1},
63 | {year: date.getFullYear()},
64 | ]},
65 | {journal_volume: [
66 | {volume: data.volume},
67 | ]},
68 | {issue: data.issue},
69 | ]},
70 |
71 | {journal_article: [
72 | {titles: [
73 | {title: data.title},
74 | ]},
75 | { contributors:
76 | data.authors.map((author, ind) => (
77 | {person_name: [
78 | { _attr: {
79 | contributor_role: 'author',
80 | sequence: (ind == 0)? 'first' : 'additional'
81 | }},
82 | {given_name: author.firstName},
83 | {surname: author.lastName},
84 | {affiliation: author.affiliation}
85 | // TODO: ORCID?
86 | ]}
87 | ))
88 | },
89 | {publication_date: [
90 | {month: date.getMonth()+1},
91 | {day: date.getDate()},
92 | {year: date.getFullYear()}
93 | ]},
94 | { publisher_item: [
95 | {item_number: data.doi}
96 | ]},
97 | {doi_data: [
98 | {doi: data.doi},
99 | //{timestamp: ""},
100 | {resource: data.url},
101 | ]},
102 | {citation_list:
103 | data.citations.map(key =>
104 | citation_xml(key, data.bibliography[key]))
105 | }
106 |
107 | ]},
108 |
109 | ]},
110 | ]},
111 | ]};
112 |
113 | return xml(crf_data);
114 | }
115 |
116 | function citation_xml(key, ent){
117 | if (ent == undefined) return {};
118 | var info = [];
119 | info.push({_attr: {key: key}});
120 | if ('title' in ent)
121 | info.push({article_title: ent.title});
122 | if ('author' in ent)
123 | info.push({author: ent.author.split(' and ')[0].split(',')[0].trim()});
124 | if ('journal' in ent)
125 | info.push({journal_title: ent.journal});
126 | if ('booktitle' in ent)
127 | info.push({volume_title: ent.booktitle});
128 | if ('volume' in ent)
129 | info.push({volume: ent.volume});
130 | if ('issue' in ent)
131 | info.push({issue: ent.issue});
132 | if ('doi' in ent)
133 | info.push({doi: ent.doi});
134 | return {citation: info};
135 | }
136 |
137 | function xml(obj) {
138 | //console.log(typeof(obj), obj)
139 | if (typeof obj === 'string') return obj;
140 | if (typeof obj === 'number') return ''+obj;
141 | let keys = Object.keys(obj);
142 | if (keys.length != 1) console.error('can\'t interpret ', obj, 'as xml');
143 | let name = keys[0];
144 | var full_content = obj[name];
145 | var attr = {};
146 | if (Array.isArray(full_content)){
147 | var content = [];
148 | for (var i in full_content) {
149 | var obj = full_content[i];
150 | var obj_name = Object.keys(obj)[0];
151 | if ('_attr' == obj_name) {
152 | attr = obj['_attr'];
153 | } else {
154 | //console.log(Object.keys(obj)[0])
155 | content.push(obj);
156 | }
157 | }
158 | } else {
159 | content = full_content;
160 | }
161 | if (content == undefined){
162 | content = 'undefined';
163 | }
164 |
165 | let attr_string = '';
166 | for (var k in attr) {
167 | attr_string += ` ${k}=\"${attr[k]}\"`;
168 | }
169 |
170 | //console.log(typeof content, Array.isArray(content), content instanceof String, content)
171 | if (Array.isArray(content)){
172 | content = content.map(xml);
173 | content = content.join('\n').split('\n');
174 | content = content.map(s => ' ' + s).join('\n');
175 | var result = `<${name}${attr_string}>\n${content}\n${name}>`;
176 | } else {
177 | content = xml(content);
178 | var result = `<${name}${attr_string}>${content}${name}>`;
179 | }
180 | return result;
181 | }
182 |
--------------------------------------------------------------------------------
/src/components/d-figure.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // Figure
16 | //
17 | // d-figure provides a state-machine of visibility events:
18 | //
19 | // scroll out of view
20 | // +----------------+
21 | // *do work here* | |
22 | // +----------------+ +-+---------+ +-v---------+
23 | // | ready +----> onscreen | | offscreen |
24 | // +----------------+ +---------^-+ +---------+-+
25 | // | |
26 | // +----------------+
27 | // scroll into view
28 | //
29 |
30 | export class Figure extends HTMLElement {
31 |
32 | static get is() { return 'd-figure'; }
33 |
34 | static get readyQueue() {
35 | if (!Figure._readyQueue) {
36 | Figure._readyQueue = [];
37 | }
38 | return Figure._readyQueue;
39 | }
40 |
41 | static addToReadyQueue(figure) {
42 | if (Figure.readyQueue.indexOf(figure) === -1) {
43 | Figure.readyQueue.push(figure);
44 | Figure.runReadyQueue();
45 | }
46 | }
47 |
48 | static runReadyQueue() {
49 | // console.log("Checking to run readyQueue, length: " + Figure.readyQueue.length + ", scrolling: " + Figure.isScrolling);
50 | // if (Figure.isScrolling) return;
51 | // console.log("Running ready Queue");
52 | const figure = Figure.readyQueue
53 | .sort((a,b) => a._seenOnScreen - b._seenOnScreen )
54 | .filter((figure) => !figure._ready)
55 | .pop();
56 | if (figure) {
57 | figure.ready();
58 | requestAnimationFrame(Figure.runReadyQueue);
59 | }
60 |
61 | }
62 |
63 | constructor() {
64 | super();
65 | // debugger
66 | this._ready = false;
67 | this._onscreen = false;
68 | this._offscreen = true;
69 | }
70 |
71 | connectedCallback() {
72 | this.loadsWhileScrolling = this.hasAttribute('loadsWhileScrolling');
73 | Figure.marginObserver.observe(this);
74 | Figure.directObserver.observe(this);
75 | }
76 |
77 | disconnectedCallback() {
78 | Figure.marginObserver.unobserve(this);
79 | Figure.directObserver.unobserve(this);
80 | }
81 |
82 | // We use two separate observers:
83 | // One with an extra 1000px margin to warn if the viewpoint gets close,
84 | // And one for the actual on/off screen events
85 |
86 | static get marginObserver() {
87 | if (!Figure._marginObserver) {
88 | // if (!('IntersectionObserver' in window)) {
89 | // throw new Error('no interscetionobbserver!');
90 | // }
91 | const viewportHeight = window.innerHeight;
92 | const margin = Math.floor(2 * viewportHeight);
93 | const options = {rootMargin: margin + 'px 0px ' + margin + 'px 0px', threshold: 0.01};
94 | const callback = Figure.didObserveMarginIntersection;
95 | const observer = new IntersectionObserver(callback, options);
96 | Figure._marginObserver = observer;
97 | }
98 | return Figure._marginObserver;
99 | }
100 |
101 | static didObserveMarginIntersection(entries) {
102 | for (const entry of entries) {
103 | const figure = entry.target;
104 | if (entry.isIntersecting && !figure._ready) {
105 | Figure.addToReadyQueue(figure);
106 | }
107 | }
108 | }
109 |
110 | static get directObserver() {
111 | if (!Figure._directObserver) {
112 | Figure._directObserver = new IntersectionObserver(
113 | Figure.didObserveDirectIntersection, {
114 | rootMargin: '0px', threshold: [0, 1.0],
115 | }
116 | );
117 | }
118 | return Figure._directObserver;
119 | }
120 |
121 | static didObserveDirectIntersection(entries) {
122 | for (const entry of entries) {
123 | const figure = entry.target;
124 | if (entry.isIntersecting) {
125 | figure._seenOnScreen = new Date();
126 | // if (!figure._ready) { figure.ready(); }
127 | if (figure._offscreen) { figure.onscreen(); }
128 | } else {
129 | if (figure._onscreen) { figure.offscreen(); }
130 | }
131 | }
132 | }
133 |
134 | // Notify listeners that registered late, too:
135 |
136 | addEventListener(eventName, callback) {
137 | super.addEventListener(eventName, callback);
138 | // if we had already dispatched something while presumingly no one was listening, we do so again
139 | // debugger
140 | if (eventName === 'ready') {
141 | if (Figure.readyQueue.indexOf(this) !== -1) {
142 | this._ready = false;
143 | Figure.runReadyQueue();
144 | }
145 | }
146 | if (eventName === 'onscreen') {
147 | this.onscreen();
148 | }
149 | }
150 |
151 | // Custom Events
152 |
153 | ready() {
154 | // debugger
155 | this._ready = true;
156 | Figure.marginObserver.unobserve(this);
157 | const event = new CustomEvent('ready');
158 | this.dispatchEvent(event);
159 | }
160 |
161 | onscreen() {
162 | this._onscreen = true;
163 | this._offscreen = false;
164 | const event = new CustomEvent('onscreen');
165 | this.dispatchEvent(event);
166 | }
167 |
168 | offscreen() {
169 | this._onscreen = false;
170 | this._offscreen = true;
171 | const event = new CustomEvent('offscreen');
172 | this.dispatchEvent(event);
173 | }
174 |
175 | }
176 |
177 | if (typeof window !== 'undefined') {
178 |
179 | Figure.isScrolling = false;
180 | let timeout;
181 | const resetTimer = () => {
182 | Figure.isScrolling = true;
183 | clearTimeout(timeout);
184 | timeout = setTimeout(() => {
185 | Figure.isScrolling = false;
186 | Figure.runReadyQueue();
187 | }, 500);
188 | };
189 | window.addEventListener('scroll', resetTimer, true);
190 |
191 | }
192 |
--------------------------------------------------------------------------------
/src/helpers/citation.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | export function collect_citations(dom = document) {
16 | const citations = new Set();
17 | const citeTags = dom.querySelectorAll("d-cite");
18 | for (const tag of citeTags) {
19 | const keyString = tag.getAttribute("key") || tag.getAttribute("bibtex-key");
20 | const keys = keyString.split(",").map(k => k.trim());
21 | for (const key of keys) {
22 | citations.add(key);
23 | }
24 | }
25 | return [...citations];
26 | }
27 |
28 | export function inline_cite_short(keys) {
29 | function cite_string(key) {
30 | if (key in data.bibliography) {
31 | var n = data.citations.indexOf(key) + 1;
32 | return "" + n;
33 | } else {
34 | return "?";
35 | }
36 | }
37 | return "[" + keys.map(cite_string).join(", ") + "]";
38 | }
39 |
40 | export function inline_cite_long(keys) {
41 | function cite_string(key) {
42 | if (key in data.bibliography) {
43 | var ent = data.bibliography[key];
44 | var names = ent.author.split(" and ");
45 | names = names.map(name => name.split(",")[0].trim());
46 | var year = ent.year;
47 | if (names.length == 1) return names[0] + ", " + year;
48 | if (names.length == 2) return names[0] + " & " + names[1] + ", " + year;
49 | if (names.length > 2) return names[0] + ", et al., " + year;
50 | } else {
51 | return "?";
52 | }
53 | }
54 | return keys.map(cite_string).join(", ");
55 | }
56 |
57 | function author_string(ent, template, sep, finalSep) {
58 | if (ent.author == null) {
59 | return "";
60 | }
61 | var names = ent.author.split(" and ");
62 | let name_strings = names.map(name => {
63 | name = name.trim();
64 | if (name.indexOf(",") != -1) {
65 | var last = name.split(",")[0].trim();
66 | var firsts = name.split(",")[1];
67 | } else if (name.indexOf(" ") != -1) {
68 | var last = name
69 | .split(" ")
70 | .slice(-1)[0]
71 | .trim();
72 | var firsts = name
73 | .split(" ")
74 | .slice(0, -1)
75 | .join(" ");
76 | } else {
77 | var last = name.trim();
78 | }
79 | var initials = "";
80 | if (firsts != undefined) {
81 | initials = firsts
82 | .trim()
83 | .split(" ")
84 | .map(s => s.trim()[0]);
85 | initials = initials.join(".") + ".";
86 | }
87 | return template
88 | .replace("${F}", firsts)
89 | .replace("${L}", last)
90 | .replace("${I}", initials)
91 | .trim(); // in case one of first or last was empty
92 | });
93 | if (names.length > 1) {
94 | var str = name_strings.slice(0, names.length - 1).join(sep);
95 | str += (finalSep || sep) + name_strings[names.length - 1];
96 | return str;
97 | } else {
98 | return name_strings[0];
99 | }
100 | }
101 |
102 | function venue_string(ent) {
103 | var cite = ent.journal || ent.booktitle || "";
104 | if ("volume" in ent) {
105 | var issue = ent.issue || ent.number;
106 | issue = issue != undefined ? "(" + issue + ")" : "";
107 | cite += ", Vol " + ent.volume + issue;
108 | }
109 | if ("pages" in ent) {
110 | cite += ", pp. " + ent.pages;
111 | }
112 | if (cite != "") cite += ". ";
113 | if ("publisher" in ent) {
114 | cite += ent.publisher;
115 | if (cite[cite.length - 1] != ".") cite += ".";
116 | }
117 | return cite;
118 | }
119 |
120 | function link_string(ent) {
121 | if ("url" in ent) {
122 | var url = ent.url;
123 | var arxiv_match = /arxiv\.org\/abs\/([0-9\.]*)/.exec(url);
124 | if (arxiv_match != null) {
125 | url = `http://arxiv.org/pdf/${arxiv_match[1]}.pdf`;
126 | }
127 |
128 | if (url.slice(-4) == ".pdf") {
129 | var label = "PDF";
130 | } else if (url.slice(-5) == ".html") {
131 | var label = "HTML";
132 | }
133 | return ` [${label || "link"}]`;
134 | } /* else if ("doi" in ent){
135 | return ` [DOI]`;
136 | }*/ else {
137 | return "";
138 | }
139 | }
140 | function doi_string(ent, new_line) {
141 | if ("doi" in ent) {
142 | return `${new_line ? "
" : ""} DOI: ${ent.doi}`;
145 | } else {
146 | return "";
147 | }
148 | }
149 |
150 | function title_string(ent) {
151 | return '' + ent.title + " ";
152 | }
153 |
154 | export function bibliography_cite(ent, fancy) {
155 | if (ent) {
156 | var cite = title_string(ent);
157 | cite += link_string(ent) + "
";
158 | if (ent.author) {
159 | cite += author_string(ent, "${L}, ${I}", ", ", " and ");
160 | if (ent.year || ent.date) {
161 | cite += ", ";
162 | }
163 | }
164 | if (ent.year || ent.date) {
165 | cite += (ent.year || ent.date) + ". ";
166 | } else {
167 | cite += ". ";
168 | }
169 | cite += venue_string(ent);
170 | cite += doi_string(ent);
171 | return cite;
172 | /*var cite = author_string(ent, "${L}, ${I}", ", ", " and ");
173 | if (ent.year || ent.date){
174 | cite += ", " + (ent.year || ent.date) + ". "
175 | } else {
176 | cite += ". "
177 | }
178 | cite += "" + ent.title + ". ";
179 | cite += venue_string(ent);
180 | cite += doi_string(ent);
181 | cite += link_string(ent);
182 | return cite*/
183 | } else {
184 | return "?";
185 | }
186 | }
187 |
188 | export function hover_cite(ent) {
189 | if (ent) {
190 | var cite = "";
191 | cite += "" + ent.title + "";
192 | cite += link_string(ent);
193 | cite += "
";
194 |
195 | var a_str = author_string(ent, "${I} ${L}", ", ") + ".";
196 | var v_str =
197 | venue_string(ent).trim() + " " + ent.year + ". " + doi_string(ent, true);
198 |
199 | if ((a_str + v_str).length < Math.min(40, ent.title.length)) {
200 | cite += a_str + " " + v_str;
201 | } else {
202 | cite += a_str + "
" + v_str;
203 | }
204 | return cite;
205 | } else {
206 | return "?";
207 | }
208 | }
209 |
210 | //https://scholar.google.com/scholar?q=allintitle%3ADocument+author%3Aolah
211 | function get_GS_URL(ent) {
212 | if (ent) {
213 | var names = ent.author.split(" and ");
214 | names = names.map(name => name.split(",")[0].trim());
215 | var title = ent.title.split(" "); //.replace(/[,:]/, "")
216 | var url = "http://search.labs.crossref.org/dois?"; //""https://scholar.google.com/scholar?"
217 | url += uris({ q: names.join(" ") + " " + title.join(" ") });
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/src/transforms/meta.js:
--------------------------------------------------------------------------------
1 | // Copyright 2018 The Distill Template Authors
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // TODO: rewrite as template to make order dependencies easier
16 |
17 | import favicon from '../assets/distill-favicon.base64';
18 | import escape from 'escape-html';
19 |
20 | export default function(dom, data) {
21 | let head = dom.querySelector('head');
22 | let appendHead = html => appendHtml(head, html);
23 |
24 | function meta(name, content, force) {
25 | if (content || force)
26 | appendHead(` \n`);
27 | }
28 |
29 | appendHead(`
30 |
31 |
32 |
33 | `);
34 |
35 | if (data.title) {
36 | appendHead(`
37 | 
A Brief Survey of Techniques
69 | Citations
90 | Displaying code snippets
104 |
120 |
121 |
145 |
122 |
126 |
127 |
128 | First
123 | Second
124 | Third
125 |
129 |
133 | 23
130 | 654
131 | 23
132 |
134 |
138 | 14
135 | 54
136 | 34
137 |
139 |
143 |
144 | 234
140 | 54
141 | 23
142 | Contributions
174 | Reviewers
176 |