diff --git a/README.md b/README.md index 50f6c2a..6c7e968 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,25 @@ -# Distill Templates +# Distill Template [![Build Status](https://travis-ci.org/distillpub/template.svg?branch=master)](https://travis-ci.org/distillpub/template) + +This is the repository for the distill web framework. If you're interesting in just using the framework to write an article for the [Distill journal](http://distill.pub), visit http://distill.pub/guide/. + +The general process for using this framework is to hotlink the compiled code in your dev environment. + +```html + +``` + +You can also install it as a local dependency through npm or with [yarn](https://yarnpkg.com). + +``` +npm install --D distill-template +``` + +If you're interested in submitting pull requests or developing on the framework itself, read on. ## Development -Run `yarn start` to start a watching build rollup server. +Run `npm run start` to start a watching build rollup server. To view the sample pages in the repo, you can run `npm run serve` as a separate process which starts a static server. `npm run build` will run a one-time build. ## 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
--[ ] h numbering: - h2: position relative - a: position: absolute; - right: calc(100% + 16px); - /* text-align: right; */ - /* width: 80px; */ - /* font-size: 20px; */ - /* font-weight: 200; */ - - -auto-added elements: - title in front, no h1 -> add it - no title in front, h1 -> read and put into frontMatter - footnote -> footnote list - break up bib - if citation, no bib-list -> add citation-list - if authors, no byline -> add byline - no appendix -> add appendix - \ No newline at end of file +Run `npm test`. That's it. diff --git a/examples/article.html b/examples/article.html index aaa2100..ddb993e 100644 --- a/examples/article.html +++ b/examples/article.html @@ -128,4 +128,6 @@ + + diff --git a/examples/tutorial.html b/examples/tutorial.html index 3473da8..0ed3074 100644 --- a/examples/tutorial.html +++ b/examples/tutorial.html @@ -164,7 +164,7 @@ }

The citation is presented inline like this: (a number that displays more information on hover). If you have an appendix, a bibliography is automatically created and populated in it.

-

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.

+

Distill chose a numerical inline citation style to improve readability of citation dense articles and because many of the benefits of longer citations are obviated by displaying more information on hover. However, we consider it good style to mention author last names if you discuss something at length and it fits into the flow well -- the authors are human and it's nice for them to have the community associate them with their work.


diff --git a/package-lock.json b/package-lock.json index 3e374c0..84c0e8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1587,6 +1587,11 @@ "is-arrayish": "0.2.1" } }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", diff --git a/package.json b/package.json index 67e8a65..4ef0d41 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "d3-scale": "^1.0.6", "d3-selection": "^1.1.0", "d3-time-format": "^2.0.3", + "escape-html": "^1.0.3", "intersection-observer": "^0.4.0", "jsdom-wc": "^11.0.0-alpha-1", "katex": "^0.7.1" diff --git a/src/components/d-byline.js b/src/components/d-byline.js index c518adc..7bead09 100644 --- a/src/components/d-byline.js +++ b/src/components/d-byline.js @@ -27,11 +27,15 @@ export function bylineTemplate(frontMatter) {

Published

-

${frontMatter.publishedMonth}. ${frontMatter.publishedDay} ${frontMatter.publishedYear}

+ ${frontMatter.published ? ` +

${frontMatter.publishedMonth}. ${frontMatter.publishedDay} ${frontMatter.publishedYear}

` : ` +

Not yet published

`}

DOI

-

${frontMatter.doi}

+ ${frontMatter.doi ? ` +

${frontMatter.doi}

` : ` +

No DOI yet

`}
`; diff --git a/src/components/d-code.js b/src/components/d-code.js index 8536492..a6b62e8 100644 --- a/src/components/d-code.js +++ b/src/components/d-code.js @@ -1,6 +1,13 @@ import Prism from 'prismjs'; import 'prismjs/components/prism-python'; import 'prismjs/components/prism-clike'; +import 'prismjs/components/prism-python'; +import 'prismjs/components/prism-clike'; +import 'prismjs/components/prism-lua'; +import 'prismjs/components/prism-bash'; +import 'prismjs/components/prism-go'; +import 'prismjs/components/prism-markdown'; +import 'prismjs/components/prism-julia'; import css from 'prismjs/themes/prism.css'; import { Template } from '../mixins/template.js'; @@ -43,7 +50,7 @@ export class Code extends Mutating(T(HTMLElement)) { } const language = Prism.languages[this.languageName]; if (language == undefined) { - console.warn(`Distill does not yet support highlighting your code block in "${this.languageName}".`); + console.warn(`Distill does not yet support highlighting your code block in "${this.languageName}'.`); return; } diff --git a/src/distill-components/distill-footer.js b/src/distill-components/distill-footer.js index 2d1cb40..87a5226 100644 --- a/src/distill-components/distill-footer.js +++ b/src/distill-components/distill-footer.js @@ -12,7 +12,6 @@ const T = Template('distill-footer', ` border-top: 1px solid rgba(0, 0, 0, 0.1); background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/ text-align: left; - contain: content; } @@ -38,16 +37,42 @@ const T = Template('distill-footer', ` } .container { - grid-column: left / text; + grid-column: text; } + +.nav { + font-size: 0.9em; + margin-top: 1.5em; +} + +.nav a { + color: rgba(255, 255, 255, 0.8); + margin-right: 6px; + text-decoration: none; +} +
- is dedicated to clear explanations of machine learning + + is dedicated to clear explanations of machine learning + + +
+ `); export class DistillFooter extends T(HTMLElement) { diff --git a/src/helpers/bibtex.js b/src/helpers/bibtex.js index 786e83a..3a2ed34 100644 --- a/src/helpers/bibtex.js +++ b/src/helpers/bibtex.js @@ -13,7 +13,7 @@ export function parseBibtex(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[key.toLowerCase()] = normalizeTag(value); } entry.entryTags.type = entry.entryType; // add to bibliography diff --git a/src/styles/d-article.css b/src/styles/d-article.css index 07b110f..cc0351b 100644 --- a/src/styles/d-article.css +++ b/src/styles/d-article.css @@ -192,3 +192,33 @@ d-figure { contain: content; display: inline-block; } + +/* Tables */ + +d-article table { + border-collapse: collapse; + margin-bottom: 1.5rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); +} + +d-article table th { + border-bottom: 1px solid rgba(0, 0, 0, 0.2); +} + +d-article table td { + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +d-article table tr:last-of-type td { + border-bottom: none; +} + +d-article table th, +d-article table td { + font-size: 15px; + padding: 2px 8px; +} + +d-article table tbody :first-child td { + padding-top: 2px; +} diff --git a/src/transforms.js b/src/transforms.js index f03a7c4..8de90bc 100644 --- a/src/transforms.js +++ b/src/transforms.js @@ -95,6 +95,7 @@ export function usesTemplateV2(dom) { return usesV2; } } + export { FrontMatter }; // TODO: removable? export const testing = { diff --git a/src/transforms/meta.js b/src/transforms/meta.js index 5f878fd..d4ffb81 100644 --- a/src/transforms/meta.js +++ b/src/transforms/meta.js @@ -1,12 +1,13 @@ import favicon from '../assets/distill-favicon.base64'; +import escape from 'escape-html'; export default function(dom, data) { let head = dom.querySelector('head'); let appendHead = html => appendHtml(head, html); - function meta(name, content) { - if (content) - appendHead(` \n`); + function meta(name, content, force) { + if (content || force) + appendHead(` \n`); } appendHead(` @@ -20,7 +21,8 @@ export default function(dom, data) { appendHead(` - + + `); (data.authors || []).forEach((a) => { @@ -34,7 +36,7 @@ export default function(dom, data) { - + `); @@ -45,7 +47,7 @@ export default function(dom, data) { - + `); @@ -63,12 +65,14 @@ export default function(dom, data) { meta('citation_doi', data.doi); let journal = data.journal || {}; - meta('citation_journal_title', journal.name); - meta('citation_journal_abbrev', journal.nameAbbrev); + meta('citation_journal_title', journal.full_title || journal.title); + meta('citation_journal_abbrev', journal.abbrev_title); meta('citation_issn', journal.issn); meta('citation_publisher', journal.publisher); + meta('citation_fulltext_world_readable', '', true); if (data.publishedDate){ + meta('citation_online_date', `${data.publishedYear}/${data.publishedMonthPadded}/${data.publishedDayPadded}`); meta('citation_publication_date', `${data.publishedYear}/${data.publishedMonthPadded}/${data.publishedDayPadded}`); } @@ -99,10 +103,33 @@ function appendHtml(el, html) { } function citation_meta_content(ref){ + // Special test for arxiv var content = `citation_title=${ref.title};`; - ref.author.split(' and ').forEach(author => { - content += `citation_author=${author.trim()};`; + + ref.author.split(' and ').forEach(name => { + name = name.trim(); + let last, firsts; + if (name.indexOf(',') != -1){ + last = name.split(',')[0].trim(); + firsts = name.split(',')[1].trim(); + } else { + last = name.split(' ').slice(-1)[0].trim(); + firsts = name.split(' ').slice(0,-1).join(' '); + } + content += `citation_author=${firsts} ${last};`; }); + + if ('year' in ref) { + content += `citation_publication_date=${ref.year};`; + } + + let arxiv_id_search = /https?:\/\/arxiv\.org\/pdf\/([0-9]*\.[0-9]*)\.pdf/.exec(ref.url); + arxiv_id_search = arxiv_id_search || /https?:\/\/arxiv\.org\/abs\/([0-9]*\.[0-9]*)/.exec(ref.url); + arxiv_id_search = arxiv_id_search || /arXiv preprint arXiv:([0-9]*\.[0-9]*)/.exec(ref.journal); + if (arxiv_id_search && arxiv_id_search[1]){ + content += `citation_arxiv_id=${arxiv_id_search[1]};`; + return content; // arXiv is not considered a journal, so we don't need journal/volume/issue + } if ('journal' in ref){ content += `citation_journal_title=${ref.journal};`; } @@ -112,7 +139,5 @@ function citation_meta_content(ref){ if ('issue' in ref || 'number' in ref){ content += `citation_number=${ref.issue || ref.number};`; } - /*content += `citation_first_page=${};`; - content += `citation_publication_date=${};`;*/ return content; } diff --git a/test/transforms.js b/test/transforms.js index 2808549..7d568b3 100644 --- a/test/transforms.js +++ b/test/transforms.js @@ -161,6 +161,41 @@ describe('Distill V2 (transforms)', function() { expect(metaTags).to.not.be.empty; }); + it('given an arxiv article, it should add a special Google scholar arxiv citation', function() { + const dom = new JSDOM('', options); + const data = { + doiSuffix: 'test-doi-suffix', + citations: ['dumoulin2016guide'], + bibliography: new Map([[ + 'dumoulin2016guide', { + title: 'A guide to convolution arithmetic for deep learning', + author: 'Dumoulin, Vincent and Visin, Francesco', + journal: 'arXiv preprint arXiv:1603.07285', + year: '2016', + url: 'https://arxiv.org/pdf/1603.07285.pdf' + } + ]]) + }; + + const meta = distill.testing.transforms.get('Meta'); + expect(meta).to.be.a('function'); + meta(dom.window.document, data); + + const metaTags = [].slice.call(dom.window.document.querySelectorAll('meta[name="citation_reference"]')); + expect(metaTags).to.not.be.empty; + + const metaTag = metaTags[0]; + expect(metaTag).to.have.property('content'); + + const content = metaTag.content; + expect(content).to.include('citation_title'); + expect(content).to.include('citation_author'); + expect(content.match(/citation_author=/g).length).to.equal(2); + expect(content).to.include('citation_publication_date'); + expect(content).to.include('citation_arxiv_id'); + expect(content).to.not.include('journal'); + }); + it('given only a DOM, it should add Google scholar references information', function() { const dom = new JSDOM(` sth