PageSourceSearch

https://shi-qingyu.github.io/rectok.github.io/template.v2.js

js shi-qingyu.github.io collected 2026-10-03 09:56:32 UTC 292,443 bytes, 9,248 lines download raw bytes

1(function (factory) {
2  typeof define === 'function' && define.amd ? define(factory) :
3  factory();
4}((function () { 'use strict';
5
6  // Copyright 2018 The Distill Template Authors
7  //
8  // Licensed under the Apache License, Version 2.0 (the "License");
9  // you may not use this file except in compliance with the License.
10  // You may obtain a copy of the License at
11  //
12  //      http://www.apache.org/licenses/LICENSE-2.0
13  //
14  // Unless required by applicable law or agreed to in writing, software
15  // distributed under the License is distributed on an "AS IS" BASIS,
16  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  // See the License for the specific language governing permissions and
18  // limitations under the License.
19
20  const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
21  const months = ['Jan.', 'Feb.', 'March', 'April', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'];
22  const zeroPad = n => n < 10 ? '0' + n : n;
23
24  const RFC = function(date) {
25    const day = days[date.getDay()].substring(0, 3);
26    const paddedDate = zeroPad(date.getDate());
27    const month = months[date.getMonth()].substring(0,3);
28    const year = date.getFullYear().toString();
29    const hours = date.getUTCHours().toString();
30    const minutes = date.getUTCMinutes().toString();
31    const seconds = date.getUTCSeconds().toString();
32    return `${day}, ${paddedDate} ${month} ${year} ${hours}:${minutes}:${seconds} Z`;
33  };
34
35  const objectFromMap = function(map) {
36    const object = Array.from(map).reduce((object, [key, value]) => (
37      Object.assign(object, { [key]: value }) // Be careful! Maps can have non-String keys; object literals can't.
38    ), {});
39    return object;
40  };
41
42  const mapFromObject = function(object) {
43    const map = new Map();
44    for (var property in object) {
45      if (object.hasOwnProperty(property)) {
46        map.set(property, object[property]);
47      }
48    }
49    return map;
50  };
51
52  class Author {
53
54    // constructor(name='', personalURL='', affiliation='', affiliationURL='') {
55    //   this.name = name; // 'Chris Olah'
56    //   this.personalURL = personalURL; // 'https://colah.github.io'
57    //   this.affiliation = affiliation; // 'Google Brain'
58    //   this.affiliationURL = affiliationURL; // 'https://g.co/brain'
59    // }
60
61    constructor(object) {
62      this.name = object.author; // 'Chris Olah'
63      this.personalURL = object.authorURL; // 'https://colah.github.io'
64      this.affiliation = object.affiliation; // 'Google Brain'
65      this.affiliationURL = object.affiliationURL; // 'https://g.co/brain'
66      this.affiliations = object.affiliations || []; // new-style affiliations
67    }
68
69    // 'Chris'
70    get firstName() {
71      const names = this.name.split(' ');
72      return names.slice(0, names.length - 1).join(' ');
73    }
74
75    // 'Olah'
76    get lastName() {
77      const names = this.name.split(' ');
78      return names[names.length -1];
79    }
80  }
81
82  function mergeFromYMLFrontmatter(target, source) {
83    target.title = source.title;
84    if (source.published) {
85      if (source.published instanceof Date) {
86        target.publishedDate = source.published;
87      } else if (source.published.constructor === String) {
88        target.publishedDate = new Date(source.published);
89      }
90    }
91    if (source.publishedDate) {
92      if (source.publishedDate instanceof Date) {
93        target.publishedDate = source.publishedDate;
94      } else if (source.publishedDate.constructor === String) {
95        target.publishedDate = new Date(source.publishedDate);
96      } else {
97        console.error('Don\'t know what to do with published date: ' + source.publishedDate);
98      }
99    }
100    target.description = source.description;
101    target.authors = source.authors.map( (authorObject) => new Author(authorObject));
102    target.katex = source.katex;
103    target.password = source.password;
104    if (source.doi) {
105      target.doi = source.doi;
106    }
107  }
108
109  class FrontMatter {
110    constructor() {
111      this.title = 'unnamed article'; // 'Attention and Augmented Recurrent Neural Networks'
112      this.description = ''; // 'A visual overview of neural attention...'
113      this.authors = []; // Array of Author(s)
114
115      this.bibliography = new Map();
116      this.bibliographyParsed = false;
117      //  {
118      //    'gregor2015draw': {
119      //      'title': 'DRAW: A recurrent neural network for image generation',
120      //      'author': 'Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan',
121      //      'journal': 'arXiv preprint arXiv:1502.04623',
122      //      'year': '2015',
123      //      'url': 'https://arxiv.org/pdf/1502.04623.pdf',
124      //      'type': 'article'
125      //    },
126      //  }
127
128      // Citation keys should be listed in the order that they are appear in the document.
129      // Each key refers to a key in the bibliography dictionary.
130      this.citations = []; // [ 'gregor2015draw', 'mercier2011humans' ]
131      this.citationsCollected = false;
132
133      //
134      // Assigned from posts.csv
135      //
136
137      //  publishedDate: 2016-09-08T07:00:00.000Z,
138      //  tags: [ 'rnn' ],
139      //  distillPath: '2016/augmented-rnns',
140      //  githubPath: 'distillpub/post--augmented-rnns',
141      //  doiSuffix: 1,
142
143      //
144      // Assigned from journal
145      //
146      this.journal = {};
147      //  journal: {
148      //    'title': 'Distill',
149      //    'full_title': 'Distill',
150      //    'abbrev_title': 'Distill',
151      //    'url': 'http://distill.pub',
152      //    'doi': '10.23915/distill',
153      //    'publisherName': 'Distill Working Group',
154      //    'publisherEmail': '[email protected]',
155      //    'issn': '2476-0757',
156      //    'editors': [...],
157      //    'committee': [...]
158      //  }
159      //  volume: 1,
160      //  issue: 9,
161
162      this.katex = {};
163
164      //
165      // Assigned from publishing process
166      //
167
168      //  githubCompareUpdatesUrl: 'https://github.com/distillpub/post--augmented-rnns/compare/1596e094d8943d2dc0ea445d92071129c6419c59...3bd9209e0c24d020f87cf6152dcecc6017cbc193',
169      //  updatedDate: 2017-03-21T07:13:16.000Z,
170      //  doi: '10.23915/distill.00001',
171      this.doi = undefined;
172      this.publishedDate = undefined;
173    }
174
175    // Example:
176    // title: Demo Title Attention and Augmented Recurrent Neural Networks
177    // published: Jan 10, 2017
178    // authors:
179    // - Chris Olah:
180    // - Shan Carter: http://shancarter.com
181    // affiliations:
182    // - Google Brain:
183    // - Google Brain: http://g.co/brain
184
185    //
186    // Computed Properties
187    //
188
189    // 'http://distill.pub/2016/augmented-rnns',
190    set url(value) {
191      this._url = value;
192    }
193    get url() {
194      if (this._url) {
195        return this._url;
196      } else if (this.distillPath && this.journal.url) {
197        return this.journal.url + '/' + this.distillPath;
198      } else if (this.journal.url) {
199        return this.journal.url;
200      }
201    }
202
203    // 'https://github.com/distillpub/post--augmented-rnns',
204    get githubUrl() {
205      if (this.githubPath) {
206        return 'https://github.com/' + this.githubPath;
207      } else {
208        return undefined;
209      }
210    }
211
212    // TODO resolve differences in naming of URL/Url/url.
213    // 'http://distill.pub/2016/augmented-rnns/thumbnail.jpg',
214    set previewURL(value) {
215      this._previewURL = value;
216    }
217    get previewURL() {
218      return this._previewURL ? this._previewURL : this.url + '/thumbnail.jpg';
219    }
220
221    // 'Thu, 08 Sep 2016 00:00:00 -0700',
222    get publishedDateRFC() {
223      return RFC(this.publishedDate);
224    }
225
226    // 'Thu, 08 Sep 2016 00:00:00 -0700',
227    get updatedDateRFC() {
228      return RFC(this.updatedDate);
229    }
230
231    // 2016,
232    get publishedYear() {
233      return this.publishedDate.getFullYear();
234    }
235
236    // 'Sept',
237    get publishedMonth() {
238      return months[this.publishedDate.getMonth()];
239    }
240
241    // 8,
242    get publishedDay() {
243      return this.publishedDate.getDate();
244    }
245
246    // '09',
247    get publishedMonthPadded() {
248      return zeroPad(this.publishedDate.getMonth() + 1);
249    }
250
251    // '08',
252    get publishedDayPadded() {
253      return zeroPad(this.publishedDate.getDate());
254    }
255
256    get publishedISODateOnly() {
257      return this.publishedDate.toISOString().split('T')[0];
258    }
259
260    get volume() {
261      const volume = this.publishedYear - 2015;
262      if (volume < 1) {
263        throw new Error('Invalid publish date detected during computing volume');
264      }
265      return volume;
266    }
267
268    get issue() {
269      return this.publishedDate.getMonth() + 1;
270    }
271
272    // 'Olah & Carter',
273    get concatenatedAuthors() {
274      if (this.authors.length > 2) {
275        return this.authors[0].lastName + ', et al.';
276      } else if (this.authors.length === 2) {
277        return this.authors[0].lastName + ' & ' + this.authors[1].lastName;
278      } else if (this.authors.length === 1) {
279        return this.authors[0].lastName;
280      }
281    }
282
283    // 'Olah, Chris and Carter, Shan',
284    get bibtexAuthors() {
285      return this.authors.map(author => {
286        return author.lastName + ', ' + author.firstName;
287      }).join(' and ');
288    }
289
290    // 'olah2016attention'
291    get slug() {
292      let slug = '';
293      if (this.authors.length) {
294        slug += this.authors[0].lastName.toLowerCase();
295        slug += this.publishedYear;
296        slug += this.title.split(' ')[0].toLowerCase();
297      }
298      return slug || 'Untitled';
299    }
300
301    get bibliographyEntries() {
302      return new Map(this.citations.map( citationKey => {
303        const entry = this.bibliography.get(citationKey);
304        return [citationKey, entry];
305      }));
306    }
307
308    set bibliography(bibliography) {
309      if (bibliography instanceof Map) {
310        this._bibliography = bibliography;
311      } else if (typeof bibliography === 'object') {
312        this._bibliography = mapFromObject(bibliography);
313      }
314    }
315
316    get bibliography() {
317      return this._bibliography;
318    }
319
320    static fromObject(source) {
321      const frontMatter = new FrontMatter();
322      Object.assign(frontMatter, source);
323      return frontMatter;
324    }
325
326    assignToObject(target) {
327      Object.assign(target, this);
328      target.bibliography = objectFromMap(this.bibliographyEntries);
329      target.url = this.url;
330      target.doi = this.doi;
331      target.githubUrl = this.githubUrl;
332      target.previewURL = this.previewURL;
333      if (this.publishedDate) {
334        target.volume = this.volume;
335        target.issue = this.issue;
336        target.publishedDateRFC = this.publishedDateRFC;
337        target.publishedYear = this.publishedYear;
338        target.publishedMonth = this.publishedMonth;
339        target.publishedDay = this.publishedDay;
340        target.publishedMonthPadded = this.publishedMonthPadded;
341        target.publishedDayPadded = this.publishedDayPadded;
342      }
343      if (this.updatedDate) {
344        target.updatedDateRFC = this.updatedDateRFC;
345      }
346      target.concatenatedAuthors = this.concatenatedAuthors;
347      target.bibtexAuthors = this.bibtexAuthors;
348      target.slug = this.slug;
349    }
350
351  }
352
353  // Copyright 2018 The Distill Template Authors
354  //
355  // Licensed under the Apache License, Version 2.0 (the "License");
356  // you may not use this file except in compliance with the License.
357  // You may obtain a copy of the License at
358  //
359  //      http://www.apache.org/licenses/LICENSE-2.0
360  //
361  // Unless required by applicable law or agreed to in writing, software
362  // distributed under the License is distributed on an "AS IS" BASIS,
363  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
364  // See the License for the specific language governing permissions and
365  // limitations under the License.
366
367  const Mutating = (superclass) => {
368    return class extends superclass {
369
370      constructor() {
371        super();
372
373        // set up mutation observer
374        const options = {childList: true, characterData: true, subtree: true};
375        const observer = new MutationObserver( () => {
376          observer.disconnect();
377          this.renderIfPossible();
378          observer.observe(this, options);
379        });
380
381        // ...and listen for changes
382        observer.observe(this, options);
383      }
384
385      connectedCallback() {
386        super.connectedCallback();
387
388        this.renderIfPossible();
389      }
390
391      // potential TODO: check if this is enough for all our usecases
392      // maybe provide a custom function to tell if we have enough information to render
393      renderIfPossible() {
394        if (this.textContent && this.root) {
395          this.renderContent();
396        }
397      }
398
399      renderContent() {
400        console.error(`Your class ${this.constructor.name} must provide a custom renderContent() method!` );
401      }
402
403    }; // end class
404  }; // end mixin function
405
406  // Copyright 2018 The Distill Template Authors
407  //
408  // Licensed under the Apache License, Version 2.0 (the "License");
409  // you may not use this file except in compliance with the License.
410  // You may obtain a copy of the License at
411  //
412  //      http://www.apache.org/licenses/LICENSE-2.0
413  //
414  // Unless required by applicable law or agreed to in writing, software
415  // distributed under the License is distributed on an "AS IS" BASIS,
416  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
417  // See the License for the specific language governing permissions and
418  // limitations under the License.
419
420  /*global ShadyCSS*/
421
422  const Template = (name, templateString, useShadow = true) => {
423
424    return (superclass) => {
425
426      const template = document.createElement('template');
427      template.innerHTML = templateString;
428
429      if (useShadow && 'ShadyCSS' in window) {
430        ShadyCSS.prepareTemplate(template, name);
431      }
432
433      return class extends superclass {
434
435        static get is() { return name; }
436
437        constructor() {
438          super();
439
440          this.clone = document.importNode(template.content, true);
441          if (useShadow) {
442            this.attachShadow({mode: 'open'});
443            this.shadowRoot.appendChild(this.clone);
444          }
445        }
446
447        connectedCallback() {
448          if (this.hasAttribute('distill-prerendered')) {
449            return;
450          }
451          if (useShadow) {
452            if ('ShadyCSS' in window) {
453              ShadyCSS.styleElement(this);
454            }
455          } else {
456            this.insertBefore(this.clone, this.firstChild);
457          }
458        }
459
460        get root() {
461          if (useShadow) {
462            return this.shadowRoot;
463          } else {
464            return this;
465          }
466        }
467
468        /* TODO: Are we using these? Should we even? */
469        $(query) {
470          return this.root.querySelector(query);
471        }
472
473        $$(query) {
474          return this.root.querySelectorAll(query);
475        }
476      };
477    };
478  };
479
480  var math = "/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nspan.katex-display {\n  text-align: left;\n  padding: 8px 0 8px 0;\n  margin: 0.5em 0 0.5em 1em;\n}\n\nspan.katex {\n  -webkit-font-smoothing: antialiased;\n  color: rgba(0, 0, 0, 0.8);\n  font-size: 1.18em;\n}\n";
481
482  // Copyright 2018 The Distill Template Authors
483  //
484  // Licensed under the Apache License, Version 2.0 (the "License");
485  // you may not use this file except in compliance with the License.
486  // You may obtain a copy of the License at
487  //
488  //      http://www.apache.org/licenses/LICENSE-2.0
489  //
490  // Unless required by applicable law or agreed to in writing, software
491  // distributed under the License is distributed on an "AS IS" BASIS,
492  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
493  // See the License for the specific language governing permissions and
494  // limitations under the License.
495
496  // This is a straight concatenation of code from KaTeX's contrib folder,
497  // but we aren't using some of their helpers that don't work well outside a browser environment.
498
499  /*global katex */
500
501  const findEndOfMath = function(delimiter, text, startIndex) {
502    // Adapted from
503    // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
504    let index = startIndex;
505    let braceLevel = 0;
506
507    const delimLength = delimiter.length;
508
509    while (index < text.length) {
510      const character = text[index];
511
512      if (
513        braceLevel <= 0 &&
514        text.slice(index, index + delimLength) === delimiter
515      ) {
516        return index;
517      } else if (character === "\\") {
518        index++;
519      } else if (character === "{") {
520        braceLevel++;
521      } else if (character === "}") {
522        braceLevel--;
523      }
524
525      index++;
526    }
527
528    return -1;
529  };
530
531  const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
532    const finalData = [];
533
534    for (let i = 0; i < startData.length; i++) {
535      if (startData[i].type === "text") {
536        const text = startData[i].data;
537
538        let lookingForLeft = true;
539        let currIndex = 0;
540        let nextIndex;
541
542        nextIndex = text.indexOf(leftDelim);
543        if (nextIndex !== -1) {
544          currIndex = nextIndex;
545          finalData.push({
546            type: "text",
547            data: text.slice(0, currIndex)
548          });
549          lookingForLeft = false;
550        }
551
552        while (true) {
553          // eslint-disable-line no-constant-condition
554          if (lookingForLeft) {
555            nextIndex = text.indexOf(leftDelim, currIndex);
556            if (nextIndex === -1) {
557              break;
558            }
559
560            finalData.push({
561              type: "text",
562              data: text.slice(currIndex, nextIndex)
563            });
564
565            currIndex = nextIndex;
566          } else {
567            nextIndex = findEndOfMath(
568              rightDelim,
569              text,
570              currIndex + leftDelim.length
571            );
572            if (nextIndex === -1) {
573              break;
574            }
575
576            finalData.push({
577              type: "math",
578              data: text.slice(currIndex + leftDelim.length, nextIndex),
579              rawData: text.slice(currIndex, nextIndex + rightDelim.length),
580              display: display
581            });
582
583            currIndex = nextIndex + rightDelim.length;
584          }
585
586          lookingForLeft = !lookingForLeft;
587        }
588
589        finalData.push({
590          type: "text",
591          data: text.slice(currIndex)
592        });
593      } else {
594        finalData.push(startData[i]);
595      }
596    }
597
598    return finalData;
599  };
600
601  const splitWithDelimiters = function(text, delimiters) {
602    let data = [{ type: "text", data: text }];
603    for (let i = 0; i < delimiters.length; i++) {
604      const delimiter = delimiters[i];
605      data = splitAtDelimiters(
606        data,
607        delimiter.left,
608        delimiter.right,
609        delimiter.display || false
610      );
611    }
612    return data;
613  };
614
615  /* Note: optionsCopy is mutated by this method. If it is ever exposed in the
616   * API, we should copy it before mutating.
617   */
618  const renderMathInText = function(text, optionsCopy) {
619    const data = splitWithDelimiters(text, optionsCopy.delimiters);
620    const fragment = document.createDocumentFragment();
621
622    for (let i = 0; i < data.length; i++) {
623      if (data[i].type === "text") {
624        fragment.appendChild(document.createTextNode(data[i].data));
625      } else {
626        const tag = document.createElement("d-math");
627        const math = data[i].data;
628        // Override any display mode defined in the settings with that
629        // defined by the text itself
630        optionsCopy.displayMode = data[i].display;
631        try {
632          tag.textContent = math;
633          if (optionsCopy.displayMode) {
634            tag.setAttribute("block", "");
635          }
636        } catch (e) {
637          if (!(e instanceof katex.ParseError)) {
638            throw e;
639          }
640          optionsCopy.errorCallback(
641            "KaTeX auto-render: Failed to parse `" + data[i].data + "` with ",
642            e
643          );
644          fragment.appendChild(document.createTextNode(data[i].rawData));
645          continue;
646        }
647        fragment.appendChild(tag);
648      }
649    }
650
651    return fragment;
652  };
653
654  const renderElem = function(elem, optionsCopy) {
655    for (let i = 0; i < elem.childNodes.length; i++) {
656      const childNode = elem.childNodes[i];
657      if (childNode.nodeType === 3) {
658        // Text node
659        const text = childNode.textContent;
660        if (optionsCopy.mightHaveMath(text)) {
661          const frag = renderMathInText(text, optionsCopy);
662          i += frag.childNodes.length - 1;
663          elem.replaceChild(frag, childNode);
664        }
665      } else if (childNode.nodeType === 1) {
666        // Element node
667        const shouldRender =
668          optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) ===
669          -1;
670
671        if (shouldRender) {
672          renderElem(childNode, optionsCopy);
673        }
674      }
675      // Otherwise, it's something else, and ignore it.
676    }
677  };
678
679  const defaultAutoRenderOptions = {
680    delimiters: [
681      { left: "$$", right: "$$", display: true },
682      { left: "\\[", right: "\\]", display: true },
683      { left: "\\(", right: "\\)", display: false }
684      // LaTeX uses this, but it ruins the display of normal `$` in text:
685      // {left: '$', right: '$', display: false},
686    ],
687
688    ignoredTags: [
689      "script",
690      "noscript",
691      "style",
692      "textarea",
693      "pre",
694      "code",
695      "svg"
696    ],
697
698    errorCallback: function(msg, err) {
699      console.error(msg, err);
700    }
701  };
702
703  const renderMathInElement = function(elem, options) {
704    if (!elem) {
705      throw new Error("No element provided to render");
706    }
707
708    const optionsCopy = Object.assign({}, defaultAutoRenderOptions, options);
709    const delimiterStrings = optionsCopy.delimiters.flatMap(d => [
710      d.left,
711      d.right
712    ]);
713    const mightHaveMath = text =>
714      delimiterStrings.some(d => text.indexOf(d) !== -1);
715    optionsCopy.mightHaveMath = mightHaveMath;
716    renderElem(elem, optionsCopy);
717  };
718
719  // Copyright 2018 The Distill Template Authors
720
721  const katexJSURL = 'https://distill.pub/third-party/katex/katex.min.js';
722  const katexCSSTag = '<link rel="stylesheet" href="https://distill.pub/third-party/katex/katex.min.css" crossorigin="anonymous">';
723
724  const T = Template('d-math', `
725${katexCSSTag}
726<style>
727
728:host {
729  display: inline-block;
730  contain: style;
731}
732
733:host([block]) {
734  display: block;
735}
736
737${math}
738</style>
739<span id='katex-container'></span>
740`);
741
742  // DMath, not Math, because that would conflict with the JS built-in
743  class DMath extends Mutating(T(HTMLElement)) {
744
745    static set katexOptions(options) {
746      DMath._katexOptions = options;
747      if (DMath.katexOptions.delimiters) {
748        if (!DMath.katexAdded) {
749          DMath.addKatex();
750        } else {
751          DMath.katexLoadedCallback();
752        }
753      }
754    }
755
756    static get katexOptions() {
757      if (!DMath._katexOptions) {
758        DMath._katexOptions = {
759          delimiters: [ { 'left':'$$', 'right':'$$', 'display': false } ]
760        };
761      }
762      return DMath._katexOptions;
763    }
764
765    static katexLoadedCallback() {
766      // render all d-math tags
767      const mathTags = document.querySelectorAll('d-math');
768      for (const mathTag of mathTags) {
769        mathTag.renderContent();
770      }
771      // transform inline delimited math to d-math tags
772      if (DMath.katexOptions.delimiters) {
773        renderMathInElement(document.body, DMath.katexOptions);
774      }
775    }
776
777    static addKatex() {
778      // css tag can use this convenience function
779      document.head.insertAdjacentHTML('beforeend', katexCSSTag);
780      // script tag has to be created to work properly
781      const scriptTag = document.createElement('script');
782      scriptTag.src = katexJSURL;
783      scriptTag.async = true;
784      scriptTag.onload = DMath.katexLoadedCallback;
785      scriptTag.crossorigin = 'anonymous';
786      document.head.appendChild(scriptTag);
787
788      DMath.katexAdded = true;
789    }
790
791    get options() {
792      const localOptions = { displayMode: this.hasAttribute('block') };
793      return Object.assign(localOptions, DMath.katexOptions);
794    }
795
796    connectedCallback() {
797      super.connectedCallback();
798      if (!DMath.katexAdded) {
799        DMath.addKatex();
800      }
801    }
802
803    renderContent() {
804      if (typeof katex !== 'undefined') {
805        const container = this.root.querySelector('#katex-container');
806        katex.render(this.textContent, container, this.options);
807      }
808    }
809
810  }
811
812  DMath.katexAdded = false;
813  DMath.inlineMathRendered = false;
814  window.DMath = DMath; // TODO: check if this can be removed, or if we should expose a distill global
815
816  // Copyright 2018 The Distill Template Authors
817  //
818  // Licensed under the Apache License, Version 2.0 (the "License");
819  // you may not use this file except in compliance with the License.
820  // You may obtain a copy of the License at
821  //
822  //      http://www.apache.org/licenses/LICENSE-2.0
823  //
824  // Unless required by applicable law or agreed to in writing, software
825  // distributed under the License is distributed on an "AS IS" BASIS,
826  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
827  // See the License for the specific language governing permissions and
828  // limitations under the License.
829
830  function collect_citations(dom = document) {
831    const citations = new Set();
832    const citeTags = dom.querySelectorAll("d-cite");
833    for (const tag of citeTags) {
834      const keyString = tag.getAttribute("key") || tag.getAttribute("bibtex-key");
835      const keys = keyString.split(",").map(k => k.trim());
836      for (const key of keys) {
837        citations.add(key);
838      }
839    }
840    return [...citations];
841  }
842
843  function author_string(ent, template, sep, finalSep) {
844    if (ent.author == null) {
845      return "";
846    }
847    var names = ent.author.split(" and ");
848    let name_strings = names.map(name => {
849      name = name.trim();
850      if (name.indexOf(",") != -1) {
851        var last = name.split(",")[0].trim();
852        var firsts = name.split(",")[1];
853      } else if (name.indexOf(" ") != -1) {
854        var last = name
855          .split(" ")
856          .slice(-1)[0]
857          .trim();
858        var firsts = name
859          .split(" ")
860          .slice(0, -1)
861          .join(" ");
862      } else {
863        var last = name.trim();
864      }
865      var initials = "";
866      if (firsts != undefined) {
867        initials = firsts
868          .trim()
869          .split(" ")
870          .map(s => s.trim()[0]);
871        initials = initials.join(".") + ".";
872      }
873      return template
874        .replace("${F}", firsts)
875        .replace("${L}", last)
876        .replace("${I}", initials)
877        .trim(); // in case one of first or last was empty
878    });
879    if (names.length > 1) {
880      var str = name_strings.slice(0, names.length - 1).join(sep);
881      str += (finalSep || sep) + name_strings[names.length - 1];
882      return str;
883    } else {
884      return name_strings[0];
885    }
886  }
887
888  function venue_string(ent) {
889    var cite = ent.journal || ent.booktitle || "";
890    if ("volume" in ent) {
891      var issue = ent.issue || ent.number;
892      issue = issue != undefined ? "(" + issue + ")" : "";
893      cite += ", Vol " + ent.volume + issue;
894    }
895    if ("pages" in ent) {
896      cite += ", pp. " + ent.pages;
897    }
898    if (cite != "") cite += ". ";
899    if ("publisher" in ent) {
900      cite += ent.publisher;
901      if (cite[cite.length - 1] != ".") cite += ".";
902    }
903    return cite;
904  }
905
906  function link_string(ent) {
907    if ("url" in ent) {
908      var url = ent.url;
909      var arxiv_match = /arxiv\.org\/abs\/([0-9\.]*)/.exec(url);
910      if (arxiv_match != null) {
911        url = `http://arxiv.org/pdf/${arxiv_match[1]}.pdf`;
912      }
913
914      if (url.slice(-4) == ".pdf") {
915        var label = "PDF";
916      } else if (url.slice(-5) == ".html") {
917        var label = "HTML";
918      }
919      return ` &ensp;<a href="${url}">[${label || "link"}]</a>`;
920    } /* else if ("doi" in ent){
921      return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
922    }*/ else {
923      return "";
924    }
925  }
926  function doi_string(ent, new_line) {
927    if ("doi" in ent) {
928      return `${new_line ? "<br>" : ""} <a href="https://doi.org/${
929      ent.doi
930    }" style="text-decoration:inherit;">DOI: ${ent.doi}</a>`;
931    } else {
932      return "";
933    }
934  }
935
936  function title_string(ent) {
937    return '<span class="title">' + ent.title + "</span> ";
938  }
939
940  function bibliography_cite(ent, fancy) {
941    if (ent) {
942      var cite = title_string(ent);
943      cite += link_string(ent) + "<br>";
944      if (ent.author) {
945        cite += author_string(ent, "${L}, ${I}", ", ", " and ");
946        if (ent.year || ent.date) {
947          cite += ", ";
948        }
949      }
950      if (ent.year || ent.date) {
951        cite += (ent.year || ent.date) + ". ";
952      } else {
953        cite += ". ";
954      }
955      cite += venue_string(ent);
956      cite += doi_string(ent);
957      return cite;
958      /*var cite =  author_string(ent, "${L}, ${I}", ", ", " and ");
959      if (ent.year || ent.date){
960        cite += ", " + (ent.year || ent.date) + ". "
961      } else {
962        cite += ". "
963      }
964      cite += "<b>" + ent.title + "</b>. ";
965      cite += venue_string(ent);
966      cite += doi_string(ent);
967      cite += link_string(ent);
968      return cite*/
969    } else {
970      return "?";
971    }
972  }
973
974  function hover_cite(ent) {
975    if (ent) {
976      var cite = "";
977      cite += "<strong>" + ent.title + "</strong>";
978      cite += link_string(ent);
979      cite += "<br>";
980
981      var a_str = author_string(ent, "${I} ${L}", ", ") + ".";
982      var v_str =
983        venue_string(ent).trim() + " " + ent.year + ". " + doi_string(ent, true);
984
985      if ((a_str + v_str).length < Math.min(40, ent.title.length)) {
986        cite += a_str + " " + v_str;
987      } else {
988        cite += a_str + "<br>" + v_str;
989      }
990      return cite;
991    } else {
992      return "?";
993    }
994  }
995
996  function domContentLoaded() {
997    return ['interactive', 'complete'].indexOf(document.readyState) !== -1;
998  }
999
1000  // Copyright 2018 The Distill Template Authors
1001  //
1002  // Licensed under the Apache License, Version 2.0 (the "License");
1003  // you may not use this file except in compliance with the License.
1004  // You may obtain a copy of the License at
1005  //
1006  //      http://www.apache.org/licenses/LICENSE-2.0
1007  //
1008  // Unless required by applicable law or agreed to in writing, software
1009  // distributed under the License is distributed on an "AS IS" BASIS,
1010  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1011  // See the License for the specific language governing permissions and
1012  // limitations under the License.
1013
1014  function _moveLegacyAffiliationFormatIntoArray(frontMatter) {
1015    // authors used to have propoerties "affiliation" and "affiliationURL".
1016    // We now encourage using an array for affiliations containing objects with
1017    // properties "name" and "url".
1018    for (let author of frontMatter.authors) {
1019      const hasOldStyle = Boolean(author.affiliation);
1020      const hasNewStyle = Boolean(author.affiliations);
1021      if (!hasOldStyle) continue;
1022      if (hasNewStyle) {
1023        console.warn(`Author ${author.author} has both old-style ("affiliation" & "affiliationURL") and new style ("affiliations") affiliation information!`);
1024      } else {
1025        let newAffiliation = {
1026          "name": author.affiliation
1027        };
1028        if (author.affiliationURL) newAffiliation.url = author.affiliationURL;
1029        author.affiliations = [newAffiliation];
1030      }
1031    }
1032    return frontMatter
1033  }
1034
1035  function parseFrontmatter(element) {
1036    const scriptTag = element.firstElementChild;
1037    if (scriptTag) {
1038      const type = scriptTag.getAttribute('type');
1039      if (type.split('/')[1] == 'json') {
1040        const content = scriptTag.textContent;
1041        const parsed = JSON.parse(content);
1042        return _moveLegacyAffiliationFormatIntoArray(parsed);
1043      } else {
1044        console.error('Distill only supports JSON frontmatter tags anymore; no more YAML.');
1045      }
1046    } else {
1047      console.error('You added a frontmatter tag but did not provide a script tag with front matter data in it. Please take a look at our templates.');
1048    }
1049    return {};
1050  }
1051
1052  class FrontMatter$1 extends HTMLElement {
1053
1054    static get is() { return 'd-front-matter'; }
1055
1056    constructor() {
1057      super();
1058
1059      const options = {childList: true, characterData: true, subtree: true};
1060      const observer = new MutationObserver( (entries) => {
1061        for (const entry of entries) {
1062          if (entry.target.nodeName === 'SCRIPT' || entry.type === 'characterData') {
1063            const data = parseFrontmatter(this);
1064            this.notify(data);
1065          }
1066        }
1067      });
1068      observer.observe(this, options);
1069    }
1070
1071    notify(data) {
1072      const options = { detail: data, bubbles: true };
1073      const event = new CustomEvent('onFrontMatterChanged', options);
1074      document.dispatchEvent(event);
1075    }
1076
1077  }
1078
1079  // Copyright 2018 The Distill Template Authors
1080  //
1081  // Licensed under the Apache License, Version 2.0 (the "License");
1082  // you may not use this file except in compliance with the License.
1083  // You may obtain a copy of the License at
1084  //
1085  //      http://www.apache.org/licenses/LICENSE-2.0
1086  //
1087  // Unless required by applicable law or agreed to in writing, software
1088  // distributed under the License is distributed on an "AS IS" BASIS,
1089  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1090  // See the License for the specific language governing permissions and
1091  // limitations under the License.
1092
1093  // no appendix -> add appendix
1094  // title in front, no h1 -> add it
1095  // no title in front, h1 -> read and put into frontMatter
1096  // footnote -> footnote list
1097  // break up bib
1098  // if citation, no bib-list -> add citation-list
1099
1100  // if authors, no byline -> add byline
1101
1102  function optionalComponents(dom, data) {
1103    const body = dom.body;
1104    const article = body.querySelector('d-article');
1105
1106    // If we don't have an article tag, something weird is going on—giving up.
1107    if (!article) {
1108      console.warn('No d-article tag found; skipping adding optional components!');
1109      return;
1110    }
1111
1112    let byline = dom.querySelector('d-byline');
1113    if (!byline) {
1114      if (data.authors) {
1115        byline = dom.createElement('d-byline');
1116        body.insertBefore(byline, article);
1117      } else {
1118        console.warn('No authors found in front matter; please add them before submission!');
1119      }
1120    }
1121
1122    // let title = dom.querySelector('d-title');
1123    // if (!title) {
1124    //   title = dom.createElement('d-title');
1125    //   body.insertBefore(title, byline);
1126    // }
1127
1128    // let h1 = title.querySelector('h1');
1129    // if (!h1) {
1130    //   h1 = dom.createElement('h1');
1131    //   h1.textContent = data.title;
1132    //   title.insertBefore(h1, title.firstChild);
1133    // }
1134
1135    const hasPassword = typeof data.password !== 'undefined';
1136    let interstitial = body.querySelector('d-interstitial');
1137    if (hasPassword && !interstitial) {
1138      const inBrowser = typeof window !== 'undefined';
1139      const onLocalhost = inBrowser && window.location.hostname.includes('localhost');
1140      if (!inBrowser || !onLocalhost) {
1141        interstitial = dom.createElement('d-interstitial');
1142        interstitial.password = data.password;
1143        body.insertBefore(interstitial, body.firstChild);
1144      }
1145    } else if (!hasPassword && interstitial) {
1146      interstitial.parentElement.removeChild(this);
1147    }
1148
1149    let appendix = dom.querySelector('d-appendix');
1150    if (!appendix) {
1151      appendix = dom.createElement('d-appendix');
1152      dom.body.appendChild(appendix);
1153    }
1154
1155    let footnoteList = dom.querySelector('d-footnote-list');
1156    if (!footnoteList) {
1157      footnoteList = dom.createElement('d-footnote-list');
1158      appendix.appendChild(footnoteList);
1159    }
1160
1161    let citationList = dom.querySelector('d-citation-list');
1162    if (!citationList) {
1163      citationList = dom.createElement('d-citation-list');
1164      appendix.appendChild(citationList);
1165    }
1166
1167  }
1168
1169  // Copyright 2018 The Distill Template Authors
1170
1171  const frontMatter = new FrontMatter();
1172
1173  const Controller = {
1174    frontMatter: frontMatter,
1175    waitingOn: {
1176      bibliography: [],
1177      citations: []
1178    },
1179    listeners: {
1180      onCiteKeyCreated(event) {
1181        const [citeTag, keys] = event.detail;
1182
1183        // ensure we have citations
1184        if (!frontMatter.citationsCollected) {
1185          // console.debug('onCiteKeyCreated, but unresolved dependency ("citations"). Enqueing.');
1186          Controller.waitingOn.citations.push(() =>
1187            Controller.listeners.onCiteKeyCreated(event)
1188          );
1189          return;
1190        }
1191
1192        // ensure we have a loaded bibliography
1193        if (!frontMatter.bibliographyParsed) {
1194          // console.debug('onCiteKeyCreated, but unresolved dependency ("bibliography"). Enqueing.');
1195          Controller.waitingOn.bibliography.push(() =>
1196            Controller.listeners.onCiteKeyCreated(event)
1197          );
1198          return;
1199        }
1200
1201        const numbers = keys.map(key => frontMatter.citations.indexOf(key));
1202        citeTag.numbers = numbers;
1203        const entries = keys.map(key => frontMatter.bibliography.get(key));
1204        citeTag.entries = entries;
1205      },
1206
1207      onCiteKeyChanged() {
1208        // const [citeTag, keys] = event.detail;
1209
1210        // update citations
1211        frontMatter.citations = collect_citations();
1212        frontMatter.citationsCollected = true;
1213        for (const waitingCallback of Controller.waitingOn.citations.slice()) {
1214          waitingCallback();
1215        }
1216
1217        // update bibliography
1218        const citationListTag = document.querySelector("d-citation-list");
1219        const bibliographyEntries = new Map(
1220          frontMatter.citations.map(citationKey => {
1221            return [citationKey, frontMatter.bibliography.get(citationKey)];
1222          })
1223        );
1224        citationListTag.citations = bibliographyEntries;
1225
1226        const citeTags = document.querySelectorAll("d-cite");
1227        for (const citeTag of citeTags) {
1228          console.log(citeTag);
1229          const keys = citeTag.keys;
1230          const numbers = keys.map(key => frontMatter.citations.indexOf(key));
1231          citeTag.numbers = numbers;
1232          const entries = keys.map(key => frontMatter.bibliography.get(key));
1233          citeTag.entries = entries;
1234        }
1235      },
1236
1237      onCiteKeyRemoved(event) {
1238        Controller.listeners.onCiteKeyChanged(event);
1239      },
1240
1241      onBibliographyChanged(event) {
1242        const citationListTag = document.querySelector("d-citation-list");
1243
1244        const bibliography = event.detail;
1245
1246        frontMatter.bibliography = bibliography;
1247        frontMatter.bibliographyParsed = true;
1248        for (const waitingCallback of Controller.waitingOn.bibliography.slice()) {
1249          waitingCallback();
1250        }
1251
1252        // ensure we have citations
1253        if (!frontMatter.citationsCollected) {
1254          Controller.waitingOn.citations.push(function() {
1255            Controller.listeners.onBibliographyChanged({
1256              target: event.target,
1257              detail: event.detail
1258            });
1259          });
1260          return;
1261        }
1262
1263        if (citationListTag.hasAttribute("distill-prerendered")) {
1264          console.debug("Citation list was prerendered; not updating it.");
1265        } else {
1266          const entries = new Map(
1267            frontMatter.citations.map(citationKey => {
1268              return [citationKey, frontMatter.bibliography.get(citationKey)];
1269            })
1270          );
1271          citationListTag.citations = entries;
1272        }
1273      },
1274
1275      onFootnoteChanged() {
1276        // const footnote = event.detail;
1277        //TODO: optimize to only update current footnote
1278        const footnotesList = document.querySelector("d-footnote-list");
1279        if (footnotesList) {
1280          const footnotes = document.querySelectorAll("d-footnote");
1281          footnotesList.footnotes = footnotes;
1282        }
1283      },
1284
1285      onFrontMatterChanged(event) {
1286        const data = event.detail;
1287        mergeFromYMLFrontmatter(frontMatter, data);
1288
1289        const interstitial = document.querySelector("d-interstitial");
1290        if (interstitial) {
1291          if (typeof frontMatter.password !== "undefined") {
1292            interstitial.password = frontMatter.password;
1293          } else {
1294            interstitial.parentElement.removeChild(interstitial);
1295          }
1296        }
1297
1298        const prerendered = document.body.hasAttribute("distill-prerendered");
1299        if (!prerendered && domContentLoaded()) {
1300          optionalComponents(document, frontMatter);
1301
1302          const appendix = document.querySelector("distill-appendix");
1303          if (appendix) {
1304            appendix.frontMatter = frontMatter;
1305          }
1306
1307          const byline = document.querySelector("d-byline");
1308          if (byline) {
1309            byline.frontMatter = frontMatter;
1310          }
1311
1312          if (data.katex) {
1313            DMath.katexOptions = data.katex;
1314          }
1315        }
1316      },
1317
1318      DOMContentLoaded() {
1319        if (Controller.loaded) {
1320          console.warn(
1321            "Controller received DOMContentLoaded but was already loaded!"
1322          );
1323          return;
1324        } else if (!domContentLoaded()) {
1325          console.warn(
1326            "Controller received DOMContentLoaded at document.readyState: " +
1327              document.readyState +
1328              "!"
1329          );
1330          return;
1331        } else {
1332          Controller.loaded = true;
1333          console.debug("Runlevel 4: Controller running DOMContentLoaded");
1334        }
1335
1336        const frontMatterTag = document.querySelector("d-front-matter");
1337        if (frontMatterTag) {
1338          const data = parseFrontmatter(frontMatterTag);
1339          Controller.listeners.onFrontMatterChanged({ detail: data });
1340        }
1341
1342        // Resolving "citations" dependency due to initial DOM load
1343        frontMatter.citations = collect_citations();
1344        frontMatter.citationsCollected = true;
1345        for (const waitingCallback of Controller.waitingOn.citations.slice()) {
1346          waitingCallback();
1347        }
1348
1349        if (frontMatter.bibliographyParsed) {
1350          for (const waitingCallback of Controller.waitingOn.bibliography.slice()) {
1351            waitingCallback();
1352          }
1353        }
1354
1355        const footnotesList = document.querySelector("d-footnote-list");
1356        if (footnotesList) {
1357          const footnotes = document.querySelectorAll("d-footnote");
1358          footnotesList.footnotes = footnotes;
1359        }
1360      }
1361    } // listeners
1362  }; // Controller
1363
1364  var base = "/*\n * Copyright 2018 The Distill Template Authors\n *\n * 
1364Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nhtml {\n  font-size: 14px;\n\tline-height: 1.6em;\n  /* font-family: \"Libre Franklin\", \"Helvetica Neue\", sans-serif; */\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", Arial, sans-serif;\n  /*, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";*/\n  text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n  -webkit-text-size-adjust: 100%;\n}\n\n@media(min-width: 768px) {\n  html {\n    font-size: 16px;\n  }\n}\n\nbody {\n  margin: 0;\n}\n\na {\n  color: #004276;\n}\n\nfigure {\n  margin: 0;\n}\n\ntable {\n\tborder-collapse: collapse;\n\tborder-spacing: 0;\n}\n\ntable th {\n\ttext-align: left;\n}\n\ntable thead {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n}\n\ntable thead th {\n  padding-bottom: 0.5em;\n}\n\ntable tbody :first-child td {\n  padding-top: 0.5em;\n}\n\npre {\n  overflow: auto;\n  max-width: 100%;\n}\n\np {\n  margin-top: 0;\n  margin-bottom: 1em;\n}\n\nsup, sub {\n  vertical-align: baseline;\n  position: relative;\n  top: -0.4em;\n  line-height: 1em;\n}\n\nsub {\n  top: 0.4em;\n}\n\n.kicker,\n.marker {\n  font-size: 15px;\n  font-weight: 600;\n  color: rgba(0, 0, 0, 0.5);\n}\n\n\n/* Headline */\n\n@media(min-width: 1024px) {\n  d-title h1 span {\n    display: block;\n  }\n}\n\n/* Figure */\n\nfigure {\n  position: relative;\n  margin-bottom: 2.5em;\n  margin-top: 1.5em;\n}\n\nfigcaption+figure {\n\n}\n\nfigure img {\n  width: 100%;\n}\n\nfigure svg text,\nfigure svg tspan {\n}\n\nfigcaption,\n.figcaption {\n  color: rgba(0, 0, 0, 0.6);\n  font-size: 12px;\n  line-height: 1.5em;\n}\n\n@media(min-width: 1024px) {\nfigcaption,\n.figcaption {\n    font-size: 13px;\n  }\n}\n\nfigure.external img {\n  background: white;\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);\n  padding: 18px;\n  box-sizing: border-box;\n}\n\nfigcaption a {\n  color: rgba(0, 0, 0, 0.6);\n}\n\nfigcaption b,\nfigcaption strong, {\n  font-weight: 600;\n  color: rgba(0, 0, 0, 1.0);\n}\n";
1365
1366  var layout = "/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@supports not (display: grid) {\n  .base-grid,\n  distill-header,\n  d-title,\n  d-abstract,\n  d-article,\n  d-appendix,\n  distill-appendix,\n  d-byline,\n  d-footnote-list,\n  d-citation-list,\n  distill-footer {\n    display: block;\n    padding: 8px;\n  }\n}\n\n.base-grid,\ndistill-header,\nd-title,\nd-abstract,\nd-article,\nd-appendix,\ndistill-appendix,\nd-byline,\nd-footnote-list,\nd-citation-list,\ndistill-footer {\n  display: grid;\n  justify-items: stretch;\n  grid-template-columns: [screen-start] 8px [page-start kicker-start text-start gutter-start middle-start] 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr [text-end page-end gutter-end kicker-end middle-end] 8px [screen-end];\n  grid-column-gap: 8px;\n}\n\n.grid {\n  display: grid;\n  grid-column-gap: 8px;\n}\n\n@media(min-width: 768px) {\n  .base-grid,\n  distill-header,\n  d-title,\n  d-abstract,\n  d-article,\n  d-appendix,\n  distill-appendix,\n  d-byline,\n  d-footnote-list,\n  d-citation-list,\n  distill-footer {\n    grid-template-columns: [screen-start] 1fr [page-start kicker-start middle-start text-start] 45px 45px 45px 45px 45px 45px 45px 45px [ kicker-end text-end gutter-start] 45px [middle-end] 45px [page-end gutter-end] 1fr [screen-end];\n    grid-column-gap: 16px;\n  }\n\n  .grid {\n    grid-column-gap: 16px;\n  }\n}\n\n@media(min-width: 1000px) {\n  .base-grid,\n  distill-header,\n  d-title,\n  d-abstract,\n  d-article,\n  d-appendix,\n  distill-appendix,\n  d-byline,\n  d-footnote-list,\n  d-citation-list,\n  distill-footer {\n    grid-template-columns: [screen-start] 1fr [page-start kicker-start] 50px [middle-start] 50px [text-start kicker-end] 50px 50px 50px 50px 50px 50px 50px 50px [text-end gutter-start] 50px [middle-end] 50px [page-end gutter-end] 1fr [screen-end];\n    grid-column-gap: 16px;\n  }\n\n  .grid {\n    grid-column-gap: 16px;\n  }\n}\n\n@media(min-width: 1180px) {\n  .base-grid,\n  distill-header,\n  d-title,\n  d-abstract,\n  d-article,\n  d-appendix,\n  distill-appendix,\n  d-byline,\n  d-footnote-list,\n  d-citation-list,\n  distill-footer {\n    grid-template-columns: [screen-start] 1fr [page-start kicker-start] 60px [middle-start] 60px [text-start kicker-end] 60px 60px 60px 60px 60px 60px 60px 60px [text-end gutter-start] 60px [middle-end] 60px [page-end gutter-end] 1fr [screen-end];\n    grid-column-gap: 32px;\n  }\n\n  .grid {\n    grid-column-gap: 32px;\n  }\n}\n\n\n\n\n.base-grid {\n  grid-column: screen;\n}\n\n/* .l-body,\nd-article > *  {\n  grid-column: text;\n}\n\n.l-page,\nd-title > *,\nd-figure {\n  grid-column: page;\n} */\n\n.l-gutter {\n  grid-column: gutter;\n}\n\n.l-text,\n.l-body {\n  grid-column: text;\n}\n\n.l-page {\n  grid-column: page;\n}\n\n.l-body-outset {\n  grid-column: middle;\n}\n\n.l-page-outset {\n  grid-column: page;\n}\n\n.l-screen {\n  grid-column: screen;\n}\n\n.l-screen-inset {\n  grid-column: screen;\n  padding-left: 16px;\n  padding-left: 16px;\n}\n\n\n/* Aside */\n\nd-article aside {\n  grid-column: gutter;\n  font-size: 12px;\n  line-height: 1.6em;\n  color: rgba(0, 0, 0, 0.6)\n}\n\n@media(min-width: 768px) {\n  aside {\n    grid-column: gutter;\n  }\n\n  .side {\n    grid-column: gutter;\n  }\n}\n";
1367
1368  var print = "/*\n * Copyright 2018 The Distill Template Authors\n *\n * 
1368Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@media print {\n\n  @page {\n    size: 8in 11in;\n    @bottom-right {\n      content: counter(page) \" of \" counter(pages);\n    }\n  }\n\n  html {\n    /* no general margins -- CSS Grid takes care of those */\n  }\n\n  p, code {\n    page-break-inside: avoid;\n  }\n\n  h2, h3 {\n    page-break-after: avoid;\n  }\n\n  d-header {\n    visibility: hidden;\n  }\n\n  d-footer {\n    display: none!important;\n  }\n\n}\n";
1369
1370  var byline = "/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nd-byline {\n  contain: style;\n  overflow: hidden;\n  border-top: 1px solid rgba(0, 0, 0, 0.1);\n  font-size: 0.8rem;\n  line-height: 1.8em;\n  padding: 1.5rem 0;\n  min-height: 1.8em;\n}\n\n\nd-byline .byline {\n  grid-template-columns: 1fr 1fr;\n  grid-column: text;\n}\n\n@media(min-width: 768px) {\n  d-byline .byline {\n    grid-template-columns: 1fr 1fr 1fr 1fr;\n  }\n}\n\nd-byline .authors-affiliations {\n  grid-column-end: span 2;\n  grid-template-columns: 1fr 1fr;\n  margin-bottom: 1em;\n}\n\n@media(min-width: 768px) {\n  d-byline .authors-affiliations {\n    margin-bottom: 0;\n  }\n}\n\nd-byline h3 {\n  font-size: 0.6rem;\n  font-weight: 400;\n  color: rgba(0, 0, 0, 0.5);\n  margin: 0;\n  text-transform: uppercase;\n}\n\nd-byline p {\n  margin: 0;\n}\n\nd-byline a,\nd-article d-byline a {\n  color: rgba(0, 0, 0, 0.8);\n  text-decoration: none;\n  border-bottom: none;\n}\n\nd-article d-byline a:hover {\n  text-decoration: underline;\n  border-bottom: none;\n}\n\nd-byline p.author {\n  font-weight: 500;\n}\n\nd-byline .affiliations {\n\n}\n";
1371
1372  var article = "/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nd-article {\n  contain: layout style;\n  overflow-x: hidden;\n  border-top: 1px solid rgba(0, 0, 0, 0.1);\n  padding-top: 2rem;\n  color: rgba(0, 0, 0, 0.8);\n}\n\nd-article > * {\n  grid-column: text;\n}\n\n@media(min-width: 768px) {\n  d-article {\n    font-size: 16px;\n  }\n}\n\n@media(min-width: 1024px) {\n  d-article {\n    font-size: 1.06rem;\n    line-height: 1.7em;\n  }\n}\n\n\n/* H2 */\n\n\nd-article .marker {\n  text-decoration: none;\n  border: none;\n  counter-reset: section;\n  grid-column: kicker;\n  line-height: 1.7em;\n}\n\nd-article .marker:hover {\n  border: none;\n}\n\nd-article .marker span {\n  padding: 0 3px 4px;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n  position: relative;\n  top: 4px;\n}\n\nd-article .marker:hover span {\n  color: rgba(0, 0, 0, 0.7);\n  border-bottom: 1px solid rgba(0, 0, 0, 0.7);\n}\n\nd-article h2 {\n  font-weight: 600;\n  font-size: 24px;\n  line-height: 1.25em;\n  margin: 2rem 0 1.5rem 0;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n  padding-bottom: 1rem;\n}\n\n@media(min-width: 1024px) {\n  d-article h2 {\n    font-size: 36px;\n  }\n}\n\n/* H3 */\n\nd-article h3 {\n  font-weight: 700;\n  font-size: 18px;\n  line-height: 1.4em;\n  margin-bottom: 1em;\n  margin-top: 2em;\n}\n\n@media(min-width: 1024px) {\n  d-article h3 {\n    font-size: 20px;\n  }\n}\n\n/* H4 */\n\nd-article h4 {\n  font-weight: 600;\n  text-transform: uppercase;\n  font-size: 14px;\n  line-height: 1.4em;\n}\n\nd-article a {\n  color: inherit;\n}\n\nd-article p,\nd-article ul,\nd-article ol,\nd-article blockquote {\n  margin-top: 0;\n  margin-bottom: 1em;\n  margin-left: 0;\n  margin-right: 0;\n}\n\nd-article blockquote {\n  border-left: 2px solid rgba(0, 0, 0, 0.2);\n  padding-left: 2em;\n  font-style: italic;\n  color: rgba(0, 0, 0, 0.6);\n}\n\nd-article a {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.4);\n  text-decoration: none;\n}\n\nd-article a:hover {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.8);\n}\n\nd-article .link {\n  text-decoration: underline;\n  cursor: pointer;\n}\n\nd-article ul,\nd-article ol {\n  padding-left: 24px;\n}\n\nd-article li {\n  margin-bottom: 1em;\n  margin-left: 0;\n  padding-left: 0;\n}\n\nd-article li:last-child {\n  margin-bottom: 0;\n}\n\nd-article pre {\n  font-size: 14px;\n  margin-bottom: 20px;\n}\n\nd-article hr {\n  grid-column: screen;\n  width: 100%;\n  border: none;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n  margin-top: 60px;\n  margin-bottom: 60px;\n}\n\nd-article section {\n  margin-top: 60px;\n  margin-bottom: 60px;\n}\n\nd-article span.equation-mimic {\n  font-family: georgia;\n  font-size: 115%;\n  font-style: italic;\n}\n\nd-article > d-code,\nd-article section > d-code  {\n  display: block;\n}\n\nd-article > d-math[block],\nd-article section > d-math[block]  {\n  display: block;\n}\n\n@media (max-width: 768px) {\n  d-article > d-code,\n  d-article section > d-code,\n  d-article > d-math[block],\n  d-article section > d-math[block] {\n      overflow-x: scroll;\n      -ms-overflow-style: none;  // IE 10+\n      overflow: -moz-scrollbars-none;  // Firefox\n  }\n\n  d-article > d-code::-webkit-scrollbar,\n  d-article section > d-code::-webkit-scrollbar,\n  d-article > d-math[block]::-webkit-scrollbar,\n  d-article section > d-math[block]::-webkit-scrollbar {\n    display: none;  // Safari and Chrome\n  }\n}\n\nd-article .citation {\n  color: #668;\n  cursor: pointer;\n}\n\nd-include {\n  width: auto;\n  display: block;\n}\n\nd-figure {\n  contain: layout style;\n}
1372\n\n/* KaTeX */\n\n.katex, .katex-prerendered {\n  contain: style;\n  display: inline-block;\n}\n\n/* Tables */\n\nd-article table {\n  border-collapse: collapse;\n  margin-bottom: 1.5rem;\n  border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n}\n\nd-article table th {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n}\n\nd-article table td {\n  border-bottom: 1px solid rgba(0, 0, 0, 0.05);\n}\n\nd-article table tr:last-of-type td {\n  border-bottom: none;\n}\n\nd-article table th,\nd-article table td {\n  font-size: 15px;\n  padding: 2px 8px;\n}\n\nd-article table tbody :first-child td {\n  padding-top: 2px;\n}\n";
1373
1374  var title = "/*\n * Copyright 2018 The Distill Template Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nd-title {\n  padding: 2rem 0 1.5rem;\n  contain: layout style;\n  overflow-x: hidden;\n}\n\n@media(min-width: 768px) {\n  d-title {\n    padding: 4rem 0 1.5rem;\n  }\n}\n\nd-title h1 {\n  grid-column: text;\n  font-size: 40px;\n  font-weight: 700;\n  line-height: 1.1em;\n  margin: 0 0 0.5rem;\n}\n\n@media(min-width: 768px) {\n  d-title h1 {\n    font-size: 50px;\n  }\n}\n\nd-title p {\n  font-weight: 300;\n  font-size: 1.2rem;\n  line-height: 1.55em;\n  grid-column: text;\n}\n\nd-title .status {\n  margin-top: 0px;\n  font-size: 12px;\n  color: #009688;\n  opacity: 0.8;\n  grid-column: kicker;\n}\n\nd-title .status span {\n  line-height: 1;\n  display: inline-block;\n  padding: 6px 0;\n  border-bottom: 1px solid #80cbc4;\n  font-size: 11px;\n  text-transform: uppercase;\n}\n";
1375
1376  // Copyright 2018 The Distill Template Authors
1377
1378  const styles = base + layout + title + byline + article + math + print;
1379
1380  function makeStyleTag(dom) {
1381
1382    const styleTagId = 'distill-prerendered-styles';
1383    const prerenderedTag = dom.getElementById(styleTagId);
1384    if (!prerenderedTag) {
1385      const styleTag = dom.createElement('style');
1386      styleTag.id = styleTagId;
1387      styleTag.type = 'text/css';
1388      const cssTextTag = dom.createTextNode(styles);
1389      styleTag.appendChild(cssTextTag);
1390      const firstScriptTag = dom.head.querySelector('script');
1391      dom.head.insertBefore(styleTag, firstScriptTag);
1392    }
1393
1394  }
1395
1396  // Copyright 2018 The Distill Template Authors
1397  //
1398  // Licensed under the Apache License, Version 2.0 (the "License");
1399  // you may not use this file except in compliance with the License.
1400  // You may obtain a copy of the License at
1401  //
1402  //      http://www.apache.org/licenses/LICENSE-2.0
1403  //
1404  // Unless required by applicable law or agreed to in writing, software
1405  // distributed under the License is distributed on an "AS IS" BASIS,
1406  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1407  // See the License for the specific language governing permissions and
1408  // limitations under the License.
1409
1410  function addPolyfill(polyfill, polyfillLoadedCallback) {
1411    console.debug('Runlevel 0: Polyfill required: ' + polyfill.name);
1412    const script = document.createElement('script');
1413    script.src = polyfill.url;
1414    script.async = false;
1415    if (polyfillLoadedCallback) {
1416      script.onload = function() { polyfillLoadedCallback(polyfill); };
1417    }
1418    script.onerror = function() {
1419      new Error('Runlevel 0: Polyfills failed to load script ' + polyfill.name);
1420    };
1421    document.head.appendChild(script);
1422  }
1423
1424  const polyfills = [
1425    {
1426      name: 'WebComponents',
1427      support: function() {
1428        return 'customElements' in window &&
1429               'attachShadow' in Element.prototype &&
1430               'getRootNode' in Element.prototype &&
1431               'content' in document.createElement('template') &&
1432               'Promise' in window &&
1433               'from' in Array;
1434      },
1435      url: 'https://distill.pub/third-party/polyfills/webcomponents-lite.js'
1436    }, {
1437      name: 'IntersectionObserver',
1438      support: function() {
1439        return 'IntersectionObserver' in window &&
1440               'IntersectionObserverEntry' in window;
1441      },
1442      url: 'https://distill.pub/third-party/polyfills/intersection-observer.js'
1443    },
1444  ];
1445
1446  class Polyfills {
1447
1448    static browserSupportsAllFeatures() {
1449      return polyfills.every((poly) => poly.support());
1450    }
1451
1452    static load(callback) {
1453      // Define an intermediate callback that checks if all is loaded.
1454      const polyfillLoaded = function(polyfill) {
1455        polyfill.loaded = true;
1456        console.debug('Runlevel 0: Polyfill has finished loading: ' + polyfill.name);
1457        // console.debug(window[polyfill.name]);
1458        if (Polyfills.neededPolyfills.every((poly) => poly.loaded)) {
1459          console.debug('Runlevel 0: All required polyfills have finished loading.');
1460          console.debug('Runlevel 0->1.');
1461          window.distillRunlevel = 1;
1462          callback();
1463        }
1464      };
1465      // Add polyfill script tags
1466      for (const polyfill of Polyfills.neededPolyfills) {
1467        addPolyfill(polyfill, polyfillLoaded);
1468      }
1469    }
1470
1471    static get neededPolyfills() {
1472      if (!Polyfills._neededPolyfills) {
1473        Polyfills._neededPolyfills = polyfills.filter((poly) => !poly.support());
1474      }
1475      return Polyfills._neededPolyfills;
1476    }
1477  }
1478
1479  // Copyright 2018 The Distill Template Authors
1480  //
1481  // Licensed under the Apache License, Version 2.0 (the "License");
1482  // you may not use this file except in compliance with the License.
1483  // You may obtain a copy of the License at
1484  //
1485  //      http://www.apache.org/licenses/LICENSE-2.0
1486  //
1487  // Unless required by applicable law or agreed to in writing, software
1488  // distributed under the License is distributed on an "AS IS" BASIS,
1489  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1490  // See the License for the specific language governing permissions and
1491  // limitations under the License.
1492
1493  // const marginSmall = 16;
1494  // const marginLarge = 3 * marginSmall;
1495  // const margin = marginSmall + marginLarge;
1496  // const gutter = marginSmall;
1497  // const outsetAmount = margin / 2;
1498  // const numCols = 4;
1499  // const numGutters = numCols - 1;
1500  // const columnWidth = (768 - 2 * marginLarge - numGutters * gutter) / numCols;
1501  //
1502  // const screenwidth = 768;
1503  // const pageWidth = screenwidth - 2 * marginLarge;
1504  // const bodyWidth = pageWidth - columnWidth - gutter;
1505
1506  function body(selector) {
1507    return `${selector} {
1508      grid-column: left / text;
1509    }
1510  `;
1511  }
1512
1513  // Copyright 2018 The Distill Template Authors
1514
1515  const T$1 = Template('d-abstract', `
1516<style>
1517  :host {
1518    font-size: 1.25rem;
1519    line-height: 1.6em;
1520    color: rgba(0, 0, 0, 0.7);
1521    -webkit-font-smoothing: antialiased;
1522  }
1523
1524  ::slotted(p) {
1525    margin-top: 0;
1526    margin-bottom: 1em;
1527    grid-column: text-start / middle-end;
1528  }
1529  ${body('d-abstract')}
1530</style>
1531
1532<slot></slot>
1533`);
1534
1535  class Abstract extends T$1(HTMLElement) {
1536
1537  }
1538
1539  // Copyright 2018 The Distill Template Authors
1540
1541  const T$2 = Template('d-appendix', `
1542<style>
1543
1544d-appendix {
1545  contain: layout style;
1546  font-size: 0.8em;
1547  line-height: 1.7em;
1548  margin-top: 60px;
1549  margin-bottom: 0;
1550  border-top: 1px solid rgba(0, 0, 0, 0.1);
1551  color: rgba(0,0,0,0.5);
1552  padding-top: 60px;
1553  padding-bottom: 48px;
1554}
1555
1556d-appendix h3 {
1557  grid-column: page-start / text-start;
1558  font-size: 15px;
1559  font-weight: 500;
1560  margin-top: 1em;
1561  margin-bottom: 0;
1562  color: rgba(0,0,0,0.65);
1563}
1564
1565d-appendix h3 + * {
1566  margin-top: 1em;
1567}
1568
1569d-appendix ol {
1570  padding: 0 0 0 15px;
1571}
1572
1573@media (min-width: 768px) {
1574  d-appendix ol {
1575    padding: 0 0 0 30px;
1576    margin-left: -30px;
1577  }
1578}
1579
1580d-appendix li {
1581  margin-bottom: 1em;
1582}
1583
1584d-appendix a {
1585  color: rgba(0, 0, 0, 0.6);
1586}
1587
1588d-appendix > * {
1589  grid-column: text;
1590}
1591
1592d-appendix > d-footnote-list,
1593d-appendix > d-citation-list,
1594d-appendix > distill-appendix {
1595  grid-column: screen;
1596}
1597
1598</style>
1599
1600`, false);
1601
1602  class Appendix extends T$2(HTMLElement) {
1603
1604  }
1605
1606  // Copyright 2018 The Distill Template Authors
1607  //
1608  // Licensed under the Apache License, Version 2.0 (the "License");
1609  // you may not use this file except in compliance with the License.
1610  // You may obtain a copy of the License at
1611  //
1612  //      http://www.apache.org/licenses/LICENSE-2.0
1613  //
1614  // Unless required by applicable law or agreed to in writing, software
1615  // distributed under the License is distributed on an "AS IS" BASIS,
1616  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1617  // See the License for the specific language governing permissions and
1618  // limitations under the License.
1619
1620  // import { Template } from '../mixins/template';
1621  // import { Controller } from '../controller';
1622
1623  const isOnlyWhitespace = /^\s*$/;
1624
1625  class Article extends HTMLElement {
1626    static get is() { return 'd-article'; }
1627
1628    constructor() {
1629      super();
1630
1631      new MutationObserver( (mutations) => {
1632        for (const mutation of mutations) {
1633          for (const addedNode of mutation.addedNodes) {
1634            switch (addedNode.nodeName) {
1635            case '#text': { // usually text nodes are only linebreaks.
1636              const text = addedNode.nodeValue;
1637              if (!isOnlyWhitespace.test(text)) {
1638                console.warn('Use of unwrapped text in distill articles is discouraged as it breaks layout! Please wrap any text in a <span> or <p> tag. We found the following text: ' + text);
1639                const wrapper = document.createElement('span');
1640                wrapper.innerHTML = addedNode.nodeValue;
1641                addedNode.parentNode.insertBefore(wrapper, addedNode);
1642                addedNode.parentNode.removeChild(addedNode);
1643              }
1644            } break;
1645            }
1646          }
1647        }
1648      }).observe(this, {childList: true});
1649    }
1650
1651  }
1652
1653  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
1654
1655  function createCommonjsModule(fn, module) {
1656  	return module = { exports: {} }, fn(module, module.exports), module.exports;
1657  }
1658
1659  var bibtexParse = createCommonjsModule(function (module, exports) {
1660  /* start bibtexParse 0.0.22 */
1661
1662  //Original work by Henrik Muehe (c) 2010
1663  //
1664  //CommonJS port by Mikola Lysenko 2013
1665  //
1666  //Port to Browser lib by ORCID / RCPETERS
1667  //
1668  //Issues:
1669  //no comment handling within strings
1670  //no string concatenation
1671  //no variable values yet
1672  //Grammar implemented here:
1673  //bibtex -> (string | preamble | comment | entry)*;
1674  //string -> '@STRING' '{' key_equals_value '}';
1675  //preamble -> '@PREAMBLE' '{' value '}';
1676  //comment -> '@COMMENT' '{' value '}';
1677  //entry -> '@' key '{' key ',' key_value_list '}';
1678  //key_value_list -> key_equals_value (',' key_equals_value)*;
1679  //key_equals_value -> key '=' value;
1680  //value -> value_quotes | value_braces | key;
1681  //value_quotes -> '"' .*? '"'; // not quite
1682  //value_braces -> '{' .*? '"'; // not quite
1683  (function(exports) {
1684
1685      function BibtexParser() {
1686          
1687          this.months = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
1688          this.notKey = [',','{','}',' ','='];
1689          this.pos = 0;
1690          this.input = "";
1691          this.entries = new Array();
1692
1693          this.currentEntry = "";
1694
1695          this.setInput = function(t) {
1696              this.input = t;
1697          };
1698
1699          this.getEntries = function() {
1700              return this.entries;
1701          };
1702
1703          this.isWhitespace = function(s) {
1704              return (s == ' ' || s == '\r' || s == '\t' || s == '\n');
1705          };
1706
1707          this.match = function(s, canCommentOut) {
1708              if (canCommentOut == undefined || canCommentOut == null)
1709                  canCommentOut = true;
1710              this.skipWhitespace(canCommentOut);
1711              if (this.input.substring(this.pos, this.pos + s.length) == s) {
1712                  this.pos += s.length;
1713              } else {
1714                  throw "Token mismatch, expected " + s + ", found "
1715                          + this.input.substring(this.pos);
1716              }            this.skipWhitespace(canCommentOut);
1717          };
1718
1719          this.tryMatch = function(s, canCommentOut) {
1720              if (canCommentOut == undefined || canCommentOut == null)
1721                  canCommentOut = true;
1722              this.skipWhitespace(canCommentOut);
1723              if (this.input.substring(this.pos, this.pos + s.length) == s) {
1724                  return true;
1725              } else {
1726                  return false;
1727              }        };
1728
1729          /* when search for a match all text can be ignored, not just white space */
1730          this.matchAt = function() {
1731              while (this.input.length > this.pos && this.input[this.pos] != '@') {
1732                  this.pos++;
1733              }
1734              if (this.input[this.pos] == '@') {
1735                  return true;
1736              }            return false;
1737          };
1738
1739          this.skipWhitespace = function(canCommentOut) {
1740              while (this.isWhitespace(this.input[this.pos])) {
1741                  this.pos++;
1742              }            if (this.input[this.pos] == "%" && canCommentOut == true) {
1743                  while (this.input[this.pos] != "\n") {
1744                      this.pos++;
1745                  }                this.skipWhitespace(canCommentOut);
1746              }        };
1747
1748          this.value_braces = function() {
1749              var bracecount = 0;
1750              this.match("{", false);
1751              var start = this.pos;
1752              var escaped = false;
1753              while (true) {
1754                  if (!escaped) {
1755                      if (this.input[this.pos] == '}') {
1756                          if (bracecount > 0) {
1757                              bracecount--;
1758                          } else {
1759                              var end = this.pos;
1760                              this.match("}", false);
1761                              return this.input.substring(start, end);
1762                          }                    } else if (this.input[this.pos] == '{') {
1763                          bracecount++;
1764                      } else if (this.pos >= this.input.length - 1) {
1765                          throw "Unterminated value";
1766                      }                }                if (this.input[this.pos] == '\\' && escaped == false)
1767                      escaped = true;
1768                  else
1769                      escaped = false;
1770                  this.pos++;
1771              }        };
1772
1773          this.value_comment = function() {
1774              var str = '';
1775              var brcktCnt = 0;
1776              while (!(this.tryMatch("}", false) && brcktCnt == 0)) {
1777                  str = str + this.input[this.pos];
1778                  if (this.input[this.pos] == '{')
1779                      brcktCnt++;
1780                  if (this.input[this.pos] == '}')
1781                      brcktCnt--;
1782                  if (this.pos >= this.input.length - 1) {
1783                      throw "Unterminated value:" + this.input.substring(start);
1784                  }                this.pos++;
1785              }            return str;
1786          };
1787
1788          this.value_quotes = function() {
1789              this.match('"', false);
1790              var start = this.pos;
1791              var escaped = false;
1792              while (true) {
1793                  if (!escaped) {
1794                      if (this.input[this.pos] == '"') {
1795                          var end = this.pos;
1796                          this.match('"', false);
1797                          return this.input.substring(start, end);
1798                      } else if (this.pos >= this.input.length - 1) {
1799                          throw "Unterminated value:" + this.input.substring(start);
1800                      }                }
1801                  if (this.input[this.pos] == '\\' && escaped == false)
1802                      escaped = true;
1803                  else
1804                      escaped = false;
1805                  this.pos++;
1806              }        };
1807
1808          this.single_value = function() {
1809              var start = this.pos;
1810              if (this.tryMatch("{")) {
1811                  return this.value_braces();
1812              } else if (this.tryMatch('"')) {
1813                  return this.value_quotes();
1814              } else {
1815                  var k = this.key();
1816                  if (k.match("^[0-9]+$"))
1817                      return k;
1818                  else if (this.months.indexOf(k.toLowerCase()) >= 0)
1819                      return k.toLowerCase();
1820                  else
1821                      throw "Value expected:" + this.input.substring(start) + ' for key: ' + k;
1822              
1823              }        };
1824
1825          this.value = function() {
1826              var values = [];
1827              values.push(this.single_value());
1828              while (this.tryMatch("#")) {
1829                  this.match("#");
1830                  values.push(this.single_value());
1831              }            return values.join("");
1832          };
1833
1834          this.key = function() {
1835              var start = this.pos;
1836              while (true) {
1837                  if (this.pos >= this.input.length) {
1838                      throw "Runaway key";
1839                  }                                // а-яА-Я is Cyrillic
1840                  //console.log(this.input[this.pos]);
1841                  if (this.notKey.indexOf(this.input[this.pos]) >= 0) {
1842                      return this.input.substring(start, this.pos);
1843                  } else {
1844                      this.pos++;
1845                      
1846                  }            }        };
1847
1848          this.key_equals_value = function() {
1849              var key = this.key();
1850              if (this.tryMatch("=")) {
1851                  this.match("=");
1852                  var val = this.value();
1853                  return [ key, val ];
1854              } else {
1855                  throw "... = value expected, equals sign missing:"
1856                          + this.input.substring(this.pos);
1857              }        };
1858
1859          this.key_value_list = function() {
1860              var kv = this.key_equals_value();
1861              this.currentEntry['entryTags'] = {};
1862              this.currentEntry['entryTags'][kv[0]] = kv[1];
1863              while (this.tryMatch(",")) {
1864                  this.match(",");
1865                  // fixes problems with commas at the end of a list
1866                  if (this.tryMatch("}")) {
1867                      break;
1868                  }
1869                  kv = this.key_equals_value();
1870                  this.currentEntry['entryTags'][kv[0]] = kv[1];
1871              }        };
1872
1873          this.entry_body = function(d) {
1874              this.currentEntry = {};
1875              this.currentEntry['citationKey'] = this.key();
1876              this.currentEntry['entryType'] = d.substring(1);
1877              this.match(",");
1878              this.key_value_list();
1879              this.entries.push(this.currentEntry);
1880          };
1881
1882          this.directive = function() {
1883              this.match("@");
1884              return "@" + this.key();
1885          };
1886
1887          this.preamble = function() {
1888              this.currentEntry = {};
1889              this.currentEntry['entryType'] = 'PREAMBLE';
1890              this.currentEntry['entry'] = this.value_comment();
1891              this.entries.push(this.currentEntry);
1892          };
1893
1894          this.comment = function() {
1895              this.currentEntry = {};
1896              this.currentEntry['entryType'] = 'COMMENT';
1897              this.currentEntry['entry'] = this.value_comment();
1898              this.entries.push(this.currentEntry);
1899          };
1900
1901          this.entry = function(d) {
1902              this.entry_body(d);
1903          };
1904
1905          this.bibtex = function() {
1906              while (this.matchAt()) {
1907                  var d = this.directive();
1908                  this.match("{");
1909                  if (d == "@STRING") {
1910                      this.string();
1911                  } else if (d == "@PREAMBLE") {
1912                      this.preamble();
1913                  } else if (d == "@COMMENT") {
1914                      this.comment();
1915                  } else {
1916                      this.entry(d);
1917                  }
1918                  this.match("}");
1919              }        };
1920      }    
1921      exports.toJSON = function(bibtex) {
1922          var b = new BibtexParser();
1923          b.setInput(bibtex);
1924          b.bibtex();
1925          return b.entries;
1926      };
1927
1928      /* added during hackathon don't hate on me */
1929      exports.toBibtex = function(json) {
1930          var out = '';
1931          for ( var i in json) {
1932              out += "@" + json[i].entryType;
1933              out += '{';
1934              if (json[i].citationKey)
1935                  out += json[i].citationKey + ', ';
1936              if (json[i].entry)
1937                  out += json[i].entry ;
1938              if (json[i].entryTags) {
1939                  var tags = '';
1940                  for (var jdx in json[i].entryTags) {
1941                      if (tags.length != 0)
1942                          tags += ', ';
1943                      tags += jdx + '= {' + json[i].entryTags[jdx] + '}';
1944                  }
1945                  out += tags;
1946              }
1947              out += '}\n\n';
1948          }
1949          return out;
1950          
1951      };
1952
1953  })( exports);
1954
1955  /* end bibtexParse */
1956  });
1957
1958  // Copyright 2018 The Distill Template Authors
1959
1960  function normalizeTag(string) {
1961    return string
1962      .replace(/[\t\n ]+/g, ' ')
1963      .replace(/{\\["^`.'acu~Hvs]( )?([a-zA-Z])}/g, (full, x, char) => char)
1964      .replace(/{\\([a-zA-Z])}/g, (full, char) => char);
1965  }
1966
1967  function parseBibtex(bibtex) {
1968    const bibliography = new Map();
1969    const parsedEntries = bibtexParse.toJSON(bibtex);
1970    for (const entry of parsedEntries) {
1971      // normalize tags; note entryTags is an object, not Map
1972      for (const [key, value] of Object.entries(entry.entryTags)) {
1973        entry.entryTags[key.toLowerCase()] = normalizeTag(value);
1974      }
1975      entry.entryTags.type = entry.entryType;
1976      // add to bibliography
1977      bibliography.set(entry.citationKey, entry.entryTags);
1978    }
1979    return bibliography;
1980  }
1981
1982  function serializeFrontmatterToBibtex(frontMatter) {
1983    return `@article{${frontMatter.slug},
1984  author = {${frontMatter.bibtexAuthors}},
1985  title = {${frontMatter.title}},
1986  journal = {${frontMatter.journal.title}},
1987  year = {${frontMatter.publishedYear}},
1988  note = {${frontMatter.url}},
1989  doi = {${frontMatter.doi}}
1990}`;
1991  }
1992
1993  // Copyright 2018 The Distill Template Authors
1994
1995  class Bibliography extends HTMLElement {
1996
1997    static get is() { return 'd-bibliography'; }
1998
1999    constructor() {
2000      super();
2001
2002      // set up mutation observer
2003      const options = {childList: true, characterData: true, subtree: true};
2004      const observer = new MutationObserver( (entries) => {
2005        for (const entry of entries) {
2006          if (entry.target.nodeName === 'SCRIPT' || entry.type === 'characterData') {
2007            this.parseIfPossible();
2008          }
2009        }
2010      });
2011      observer.observe(this, options);
2012    }
2013
2014    connectedCallback() {
2015      requestAnimationFrame(() => {
2016        this.parseIfPossible();
2017      });
2018    }
2019
2020    parseIfPossible() {
2021      const scriptTag = this.querySelector('script');
2022      if (!scriptTag) return;
2023      if (scriptTag.type == 'text/bibtex') {
2024        const newBibtex = scriptTag.textContent;
2025        if (this.bibtex !== newBibtex) {
2026          this.bibtex = newBibtex;
2027          const bibliography = parseBibtex(this.bibtex);
2028          this.notify(bibliography);
2029        }
2030      } else if (scriptTag.type == 'text/json') {
2031        const bibliography = new Map(JSON.parse(scriptTag.textContent));
2032        this.notify(bibliography);
2033      } else {
2034        console.warn('Unsupported bibliography script tag type: ' + scriptTag.type);
2035      }
2036    }
2037
2038    notify(bibliography) {
2039      const options = { detail: bibliography, bubbles: true };
2040      const event = new CustomEvent('onBibliographyChanged', options);
2041      this.dispatchEvent(event);
2042    }
2043
2044    /* observe 'src' attribute */
2045
2046    static get observedAttributes() {
2047      return ['src'];
2048    }
2049
2050    receivedBibtex(event) {
2051      const bibliography = parseBibtex(event.target.response);
2052      this.notify(bibliography);
2053    }
2054
2055    attributeChangedCallback(name, oldValue, newValue) {
2056      var oReq = new XMLHttpRequest();
2057      oReq.onload = (e) => this.receivedBibtex(e);
2058      oReq.onerror = () => console.warn(`Could not load Bibtex! (tried ${newValue})`);
2059      oReq.responseType = 'text';
2060      oReq.open('GET', newValue, true);
2061      oReq.send();
2062    }
2063
2064
2065  }
2066
2067  // Copyright 2018 The Distill Template Authors
2068  //
2069  // Licensed under the Apache License, Version 2.0 (the "License");
2070  // you may not use this file except in compliance with the License.
2071  // You may obtain a copy of the License at
2072  //
2073  //      http://www.apache.org/licenses/LICENSE-2.0
2074  //
2075  // Unless required by applicable law or agreed to in writing, software
2076  // distributed under the License is distributed on an "AS IS" BASIS,
2077  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2078  // See the License for the specific language governing permissions and
2079  // limitations under the License.
2080
2081  // import style from '../styles/d-byline.css';
2082
2083  function bylineTemplate(frontMatter) {
2084    return `
2085    <div class="byline grid">
2086      <div class="authors-affiliations grid">
2087        <h3>Authors</h3>
2088        <h3>Affiliations</h3>
2089        ${frontMatter.authors.map(author => `
2090          <p class="author">
2091            ${author.personalURL ? `
2092              <a class="name" href="${author.personalURL}">${author.name}</a>` : `
2093              <span class="name">${author.name}</span>`}
2094          </p>
2095          <p class="affiliation">
2096          ${author.affiliations.map(affiliation =>
2097            affiliation.url ? `<a class="affiliation" href="${affiliation.url}">${affiliation.name}</a>` : `<span class="affiliation">${affiliation.name}</span>`
2098          ).join(', ')}
2099          </p>
2100        `).join('')}
2101      </div>
2102      <div>
2103        <h3>Date</h3>
2104        ${frontMatter.publishedDate ? `
2105          <p>${frontMatter.publishedMonth} ${frontMatter.publishedDay}, ${frontMatter.publishedYear}</p> ` : `
2106          <p><em>Not published yet.</em></p>`}
2107      </div>
2108    </div>
2109    `;
2110      }
2111  
2112
2113  class Byline extends HTMLElement {
2114
2115    static get is() { return 'd-byline'; }
2116
2117    set frontMatter(frontMatter) {
2118      this.innerHTML = bylineTemplate(frontMatter);
2119    }
2120
2121  }
2122
2123  // Copyright 2018 The Distill Template Authors
2124
2125  const T$3 = Template(
2126    "d-cite",
2127    `
2128<style>
2129
2130:host {
2131  display: inline-block;
2132}
2133
2134.citation {
2135  color: hsla(206, 90%, 20%, 0.7);
2136}
2137
2138.citation-number {
2139  cursor: default;
2140  white-space: nowrap;
2141  font-family: -apple-system, BlinkMacSystemFont, "Roboto", Helvetica, sans-serif;
2142  font-size: 75%;
2143  color: hsla(206, 90%, 20%, 0.7);
2144  display: inline-block;
2145  line-height: 1.1em;
2146  text-align: center;
2147  position: relative;
2148  top: -2px;
2149  margin: 0 2px;
2150}
2151
2152figcaption .citation-number {
2153  font-size: 11px;
2154  font-weight: normal;
2155  top: -2px;
2156  line-height: 1em;
2157}
2158
2159ul {
2160  margin: 0;
2161  padding: 0;
2162  list-style-type: none;
2163}
2164
2165ul li {
2166  padding: 15px 10px 15px 10px;
2167  border-bottom: 1px solid rgba(0,0,0,0.1)
2168}
2169
2170ul li:last-of-type {
2171  border-bottom: none;
2172}
2173
2174</style>
2175
2176<d-hover-box id="hover-box"></d-hover-box>
2177
2178<div id="citation-" class="citation">
2179  <span class="citation-number"></span>
2180</div>
2181`
2182  );
2183
2184  class Cite extends T$3(HTMLElement) {
2185    /* Lifecycle */
2186    constructor() {
2187      super();
2188      this._numbers = [];
2189      this._entries = [];
2190    }
2191
2192    connectedCallback() {
2193      this.outerSpan = this.root.querySelector("#citation-");
2194      this.innerSpan = this.root.querySelector(".citation-number");
2195      this.hoverBox = this.root.querySelector("d-hover-box");
2196      window.customElements.whenDefined("d-hover-box").then(() => {
2197        this.hoverBox.listen(this);
2198      });
2199      // in case this component got connected after values were set
2200      if (this.numbers) {
2201        this.displayNumbers(this.numbers);
2202      }
2203      if (this.entries) {
2204        this.displayEntries(this.entries);
2205      }
2206    }
2207
2208    //TODO This causes an infinite loop on firefox with polyfills.
2209    // This is only needed for interactive editing so no priority.
2210    // disconnectedCallback() {
2211    // const options = { detail: [this, this.keys], bubbles: true };
2212    // const event = new CustomEvent('onCiteKeyRemoved', options);
2213    // document.dispatchEvent(event);
2214    // }
2215
2216    /* observe 'key' attribute */
2217
2218    static get observedAttributes() {
2219      return ["key", "bibtex-key"];
2220    }
2221
2222    attributeChangedCallback(name, oldValue, newValue) {
2223      const eventName = oldValue ? "onCiteKeyChanged" : "onCiteKeyCreated";
2224      const keys = newValue.split(",").map(k => k.trim());
2225      const options = { detail: [this, keys], bubbles: true };
2226      const event = new CustomEvent(eventName, options);
2227      document.dispatchEvent(event);
2228    }
2229
2230    set key(value) {
2231      this.setAttribute("key", value);
2232    }
2233
2234    get key() {
2235      return this.getAttribute("key") || this.getAttribute("bibtex-key");
2236    }
2237
2238    get keys() {
2239      const result = this.key.split(",");
2240      console.log(result);
2241      return result;
2242    }
2243
2244    /* Setters & Rendering */
2245
2246    set numbers(numbers) {
2247      this._numbers = numbers;
2248      this.displayNumbers(numbers);
2249    }
2250
2251    get numbers() {
2252      return this._numbers;
2253    }
2254
2255    displayNumbers(numbers) {
2256      if (!this.innerSpan) return;
2257      const numberStrings = numbers.map(index => {
2258        return index == -1 ? "?" : index + 1 + "";
2259      });
2260      const textContent = "[" + numberStrings.join(", ") + "]";
2261      this.innerSpan.textContent = textContent;
2262    }
2263
2264    set entries(entries) {
2265      this._entries = entries;
2266      this.displayEntries(entries);
2267    }
2268
2269    get entries() {
2270      return this._entries;
2271    }
2272
2273    displayEntries(entries) {
2274      if (!this.hoverBox) return;
2275      this.hoverBox.innerHTML = `<ul>
2276      ${entries
2277        .map(hover_cite)
2278        .map(html => `<li>${html}</li>`)
2279        .join("\n")}
2280    </ul>`;
2281    }
2282  }
2283
2284  // Copyright 2018 The Distill Template Authors
2285
2286  const styles$1 = `
2287d-citation-list {
2288  contain: style;
2289}
2290
2291d-citation-list .references {
2292  grid-column: text;
2293}
2294
2295d-citation-list .references .title {
2296  font-weight: 500;
2297}
2298`;
2299
2300  function renderCitationList(element, entries, dom=document) {
2301    if (entries.size > 0) {
2302      element.style.display = '';
2303      let list = element.querySelector('.references');
2304      if (list) {
2305        list.innerHTML = '';
2306      } else {
2307        const stylesTag = dom.createElement('style');
2308        stylesTag.innerHTML = styles$1;
2309        element.appendChild(stylesTag);
2310
2311        const heading = dom.createElement('h3');
2312        heading.id = 'references';
2313        heading.textContent = 'References';
2314        element.appendChild(heading);
2315
2316        list = dom.createElement('ol');
2317        list.id = 'references-list';
2318        list.className = 'references';
2319        element.appendChild(list);
2320      }
2321
2322      for (const [key, entry] of entries) {
2323        const listItem = dom.createElement('li');
2324        listItem.id = key;
2325        listItem.innerHTML = bibliography_cite(entry);
2326        list.appendChild(listItem);
2327      }
2328    } else {
2329      element.style.display = 'none';
2330    }
2331  }
2332
2333  class CitationList extends HTMLElement {
2334
2335    static get is() { return 'd-citation-list'; }
2336
2337    connectedCallback() {
2338      if (!this.hasAttribute('distill-prerendered')) {
2339        this.style.display = 'none';
2340      }
2341    }
2342
2343    set citations(citations) {
2344      renderCitationList(this, citations);
2345    }
2346
2347  }
2348
2349  var prism = createCommonjsModule(function (module) {
2350  /* **********************************************
2351       Begin prism-core.js
2352  ********************************************** */
2353
2354  var _self = (typeof window !== 'undefined')
2355  	? window   // if in browser
2356  	: (
2357  		(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
2358  		? self // if in worker
2359  		: {}   // if in node js
2360  	);
2361
2362  /**
2363   * Prism: Lightweight, robust, elegant syntax highlighting
2364   * MIT license http://www.opensource.org/licenses/mit-license.php/
2365   * @author Lea Verou http://lea.verou.me
2366   */
2367
2368  var Prism = (function (_self){
2369
2370  // Private helper vars
2371  var lang = /\blang(?:uage)?-([\w-]+)\b/i;
2372  var uniqueId = 0;
2373
2374
2375  var _ = {
2376  	manual: _self.Prism && _self.Prism.manual,
2377  	disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
2378  	util: {
2379  		encode: function encode(tokens) {
2380  			if (tokens instanceof Token) {
2381  				return new Token(tokens.type, encode(tokens.content), tokens.alias);
2382  			} else if (Array.isArray(tokens)) {
2383  				return tokens.map(encode);
2384  			} else {
2385  				return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
2386  			}
2387  		},
2388
2389  		type: function (o) {
2390  			return Object.prototype.toString.call(o).slice(8, -1);
2391  		},
2392
2393  		objId: function (obj) {
2394  			if (!obj['__id']) {
2395  				Object.defineProperty(obj, '__id', { value: ++uniqueId });
2396  			}
2397  			return obj['__id'];
2398  		},
2399
2400  		// Deep clone a language definition (e.g. to extend it)
2401  		clone: function deepClone(o, visited) {
2402  			var clone, id, type = _.util.type(o);
2403  			visited = visited || {};
2404
2405  			switch (type) {
2406  				case 'Object':
2407  					id = _.util.objId(o);
2408  					if (visited[id]) {
2409  						return visited[id];
2410  					}
2411  					clone = {};
2412  					visited[id] = clone;
2413
2414  					for (var key in o) {
2415  						if (o.hasOwnProperty(key)) {
2416  							clone[key] = deepClone(o[key], visited);
2417  						}
2418  					}
2419
2420  					return clone;
2421
2422  				case 'Array':
2423  					id = _.util.objId(o);
2424  					if (visited[id]) {
2425  						return visited[id];
2426  					}
2427  					clone = [];
2428  					visited[id] = clone;
2429
2430  					o.forEach(function (v, i) {
2431  						clone[i] = deepClone(v, visited);
2432  					});
2433
2434  					return clone;
2435
2436  				default:
2437  					return o;
2438  			}
2439  		},
2440
2441  		/**
2442  		 * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
2443  		 *
2444  		 * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
2445  		 *
2446  		 * @param {Element} element
2447  		 * @returns {string}
2448  		 */
2449  		getLanguage: function (element) {
2450  			while (element && !lang.test(element.className)) {
2451  				element = element.parentElement;
2452  			}
2453  			if (element) {
2454  				return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
2455  			}
2456  			return 'none';
2457  		},
2458
2459  		/**
2460  		 * Returns the script element that is currently executing.
2461  		 *
2462  		 * This does __not__ work for line script element.
2463  		 *
2464  		 * @returns {HTMLScriptElement | null}
2465  		 */
2466  		currentScript: function () {
2467  			if (typeof document === 'undefined') {
2468  				return null;
2469  			}
2470  			if ('currentScript' in document) {
2471  				return document.currentScript;
2472  			}
2473
2474  			// IE11 workaround
2475  			// we'll get the src of the current script by parsing IE11's error stack trace
2476  			// this will not work for inline scripts
2477
2478  			try {
2479  				throw new Error();
2480  			} catch (err) {
2481  				// Get file src url from stack. Specifically works with the format of stack traces in IE.
2482  				// A stack will look like this:
2483  				//
2484  				// Error
2485  				//    at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
2486  				//    at Global code (http://localhost/components/prism-core.js:606:1)
2487
2488  				var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1];
2489  				if (src) {
2490  					var scripts = document.getElementsByTagName('script');
2491  					for (var i in scripts) {
2492  						if (scripts[i].src == src) {
2493  							return scripts[i];
2494  						}
2495  					}
2496  				}
2497  				return null;
2498  			}
2499  		}
2500  	},
2501
2502  	languages: {
2503  		extend: function (id, redef) {
2504  			var lang = _.util.clone(_.languages[id]);
2505
2506  			for (var key in redef) {
2507  				lang[key] = redef[key];
2508  			}
2509
2510  			return lang;
2511  		},
2512
2513  		/**
2514  		 * Insert a token before another token in a language literal
2515  		 * As this needs to recreate the object (we cannot actually insert before keys in object literals),
2516  		 * we cannot just provide an object, we need an object and a key.
2517  		 * @param inside The key (or language id) of the parent
2518  		 * @param before The key to insert before.
2519  		 * @param insert Object with the key/value pairs to insert
2520  		 * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
2521  		 */
2522  		insertBefore: function (inside, before, insert, root) {
2523  			root = root || _.languages;
2524  			var grammar = root[inside];
2525  			var ret = {};
2526
2527  			for (var token in grammar) {
2528  				if (grammar.hasOwnProperty(token)) {
2529
2530  					if (token == before) {
2531  						for (var newToken in insert) {
2532  							if (insert.hasOwnProperty(newToken)) {
2533  								ret[newToken] = insert[newToken];
2534  							}
2535  						}
2536  					}
2537
vendor: 5,588 bytes, lines 2538-2766
2538  					// Do not insert token which also occur in insert. See #1525
2539  					if (!insert.hasOwnProperty(token)) {
2540  						ret[token] = grammar[token];
2541  					}
2542  				}
2543  			}
2544
2545  			var old = root[inside];
2546  			root[inside] = ret;
2547
2548  			// Update references in other language definitions
2549  			_.languages.DFS(_.languages, function(key, value) {
2550  				if (value === old && key != inside) {
2551  					this[key] = ret;
2552  				}
2553  			});
2554
2555  			return ret;
2556  		},
2557
2558  		// Traverse a language definition with Depth First Search
2559  		DFS: function DFS(o, callback, type, visited) {
2560  			visited = visited || {};
2561
2562  			var objId = _.util.objId;
2563
2564  			for (var i in o) {
2565  				if (o.hasOwnProperty(i)) {
2566  					callback.call(o, i, o[i], type || i);
2567
2568  					var property = o[i],
2569  					    propertyType = _.util.type(property);
2570
2571  					if (propertyType === 'Object' && !visited[objId(property)]) {
2572  						visited[objId(property)] = true;
2573  						DFS(property, callback, null, visited);
2574  					}
2575  					else if (propertyType === 'Array' && !visited[objId(property)]) {
2576  						visited[objId(property)] = true;
2577  						DFS(property, callback, i, visited);
2578  					}
2579  				}
2580  			}
2581  		}
2582  	},
2583  	plugins: {},
2584
2585  	highlightAll: function(async, callback) {
2586  		_.highlightAllUnder(document, async, callback);
2587  	},
2588
2589  	highlightAllUnder: function(container, async, callback) {
2590  		var env = {
2591  			callback: callback,
2592  			container: container,
2593  			selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
2594  		};
2595
2596  		_.hooks.run('before-highlightall', env);
2597
2598  		env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
2599
2600  		_.hooks.run('before-all-elements-highlight', env);
2601
2602  		for (var i = 0, element; element = env.elements[i++];) {
2603  			_.highlightElement(element, async === true, env.callback);
2604  		}
2605  	},
2606
2607  	highlightElement: function(element, async, callback) {
2608  		// Find language
2609  		var language = _.util.getLanguage(element);
2610  		var grammar = _.languages[language];
2611
2612  		// Set language on the element, if not present
2613  		element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
2614
2615  		// Set language on the parent, for styling
2616  		var parent = element.parentNode;
2617  		if (parent && parent.nodeName.toLowerCase() === 'pre') {
2618  			parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
2619  		}
2620
2621  		var code = element.textContent;
2622
2623  		var env = {
2624  			element: element,
2625  			language: language,
2626  			grammar: grammar,
2627  			code: code
2628  		};
2629
2630  		function insertHighlightedCode(highlightedCode) {
2631  			env.highlightedCode = highlightedCode;
2632
2633  			_.hooks.run('before-insert', env);
2634
2635  			env.element.innerHTML = env.highlightedCode;
2636
2637  			_.hooks.run('after-highlight', env);
2638  			_.hooks.run('complete', env);
2639  			callback && callback.call(env.element);
2640  		}
2641
2642  		_.hooks.run('before-sanity-check', env);
2643
2644  		if (!env.code) {
2645  			_.hooks.run('complete', env);
2646  			callback && callback.call(env.element);
2647  			return;
2648  		}
2649
2650  		_.hooks.run('before-highlight', env);
2651
2652  		if (!env.grammar) {
2653  			insertHighlightedCode(_.util.encode(env.code));
2654  			return;
2655  		}
2656
2657  		if (async && _self.Worker) {
2658  			var worker = new Worker(_.filename);
2659
2660  			worker.onmessage = function(evt) {
2661  				insertHighlightedCode(evt.data);
2662  			};
2663
2664  			worker.postMessage(JSON.stringify({
2665  				language: env.language,
2666  				code: env.code,
2667  				immediateClose: true
2668  			}));
2669  		}
2670  		else {
2671  			insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
2672  		}
2673  	},
2674
2675  	highlight: function (text, grammar, language) {
2676  		var env = {
2677  			code: text,
2678  			grammar: grammar,
2679  			language: language
2680  		};
2681  		_.hooks.run('before-tokenize', env);
2682  		env.tokens = _.tokenize(env.code, env.grammar);
2683  		_.hooks.run('after-tokenize', env);
2684  		return Token.stringify(_.util.encode(env.tokens), env.language);
2685  	},
2686
2687  	tokenize: function(text, grammar) {
2688  		var rest = grammar.rest;
2689  		if (rest) {
2690  			for (var token in rest) {
2691  				grammar[token] = rest[token];
2692  			}
2693
2694  			delete grammar.rest;
2695  		}
2696
2697  		var tokenList = new LinkedList();
2698  		addAfter(tokenList, tokenList.head, text);
2699
2700  		matchGrammar(text, tokenList, grammar, tokenList.head, 0);
2701
2702  		return toArray(tokenList);
2703  	},
2704
2705  	hooks: {
2706  		all: {},
2707
2708  		add: function (name, callback) {
2709  			var hooks = _.hooks.all;
2710
2711  			hooks[name] = hooks[name] || [];
2712
2713  			hooks[name].push(callback);
2714  		},
2715
2716  		run: function (name, env) {
2717  			var callbacks = _.hooks.all[name];
2718
2719  			if (!callbacks || !callbacks.length) {
2720  				return;
2721  			}
2722
2723  			for (var i=0, callback; callback = callbacks[i++];) {
2724  				callback(env);
2725  			}
2726  		}
2727  	},
2728
2729  	Token: Token
2730  };
2731
2732  _self.Prism = _;
2733
2734  function Token(type, content, alias, matchedStr, greedy) {
2735  	this.type = type;
2736  	this.content = content;
2737  	this.alias = alias;
2738  	// Copy of the full string this token was created from
2739  	this.length = (matchedStr || '').length|0;
2740  	this.greedy = !!greedy;
2741  }
2742
2743  Token.stringify = function stringify(o, language) {
2744  	if (typeof o == 'string') {
2745  		return o;
2746  	}
2747  	if (Array.isArray(o)) {
2748  		var s = '';
2749  		o.forEach(function (e) {
2750  			s += stringify(e, language);
2751  		});
2752  		return s;
2753  	}
2754
2755  	var env = {
2756  		type: o.type,
2757  		content: stringify(o.content, language),
2758  		tag: 'span',
2759  		classes: ['token', o.type],
2760  		attributes: {},
2761  		language: language
2762  	};
2763
2764  	var aliases = o.alias;
2765  	if (aliases) {
2766  		if (Array.isArray(aliases)) {
2767  			Array.prototype.push.apply(env.classes, aliases);
2768  		} else {
2769  			env.classes.push(aliases);
2770  		}
2771  	}
2772
2773  	_.hooks.run('wrap', env);
2774
2775  	var attributes = '';
2776  	for (var name in env.attributes) {
2777  		attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
2778  	}
2779
2780  	return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
2781  };
2782
2783  /**
2784   * @param {string} text
2785   * @param {LinkedList<string | Token>} tokenList
2786   * @param {any} grammar
2787   * @param {LinkedListNode<string | Token>} startNode
2788   * @param {number} startPos
2789   * @param {boolean} [oneshot=false]
2790   * @param {string} [target]
2791   */
2792  function matchGrammar(text, tokenList, grammar, startNode, startPos, oneshot, target) {
2793  	for (var token in grammar) {
2794  		if (!grammar.hasOwnProperty(token) || !grammar[token]) {
2795  			continue;
2796  		}
2797
2798  		var patterns = grammar[token];
2799  		patterns = Array.isArray(patterns) ? patterns : [patterns];
2800
2801  		for (var j = 0; j < patterns.length; ++j) {
2802  			if (target && target == token + ',' + j) {
2803  				return;
2804  			}
2805
2806  			var pattern = patterns[j],
2807  				inside = pattern.inside,
2808  				lookbehind = !!pattern.lookbehind,
2809  				greedy = !!pattern.greedy,
2810  				lookbehindLength = 0,
2811  				alias = pattern.alias;
2812
2813  			if (greedy && !pattern.pattern.global) {
2814  				// Without the global flag, lastIndex won't work
2815  				var flags = pattern.pattern.toString().match(/[imsuy]*$/)[0];
2816  				pattern.pattern = RegExp(pattern.pattern.source, flags + 'g');
2817  			}
2818
2819  			pattern = pattern.pattern || pattern;
2820
2821  			for ( // iterate the token list and keep track of the current token/string position
2822  				var currentNode = startNode.next, pos = startPos;
2823  				currentNode !== tokenList.tail;
2824  				pos += currentNode.value.length, currentNode = currentNode.next
2825  			) {
2826
2827  				var str = currentNode.value;
2828
2829  				if (tokenList.length > text.length) {
2830  					// Something went terribly wrong, ABORT, ABORT!
2831  					return;
2832  				}
2833
2834  				if (str instanceof Token) {
2835  					continue;
2836  				}
2837
2838  				var removeCount = 1; // this is the to parameter of removeBetween
2839
2840  				if (greedy && currentNode != tokenList.tail.prev) {
2841  					pattern.lastIndex = pos;
2842  					var match = pattern.exec(text);
2843  					if (!match) {
2844  						break;
2845  					}
2846
2847  					var from = match.index + (lookbehind && match[1] ? match[1].length : 0);
2848  					var to = match.index + match[0].length;
2849  					var p = pos;
2850
2851  					// find the node that contains the match
2852  					p += currentNode.value.length;
2853  					while (from >= p) {
2854  						currentNode = currentNode.next;
2855  						p += currentNode.value.length;
2856  					}
2857  					// adjust pos (and p)
2858  					p -= currentNode.value.length;
2859  					pos = p;
2860
2861  					// the current node is a Token, then the match starts inside another Token, which is invalid
2862  					if (currentNode.value instanceof Token) {
2863  						continue;
2864  					}
2865
2866  					// find the last node which is affected by this match
2867  					for (
2868  						var k = currentNode;
2869  						k !== tokenList.tail && (p < to || (typeof k.value === 'string' && !k.prev.value.greedy));
2870  						k = k.next
2871  					) {
2872  						removeCount++;
2873  						p += k.value.length;
2874  					}
2875  					removeCount--;
2876
2877  					// replace with the new match
2878  					str = text.slice(pos, p);
2879  					match.index -= pos;
2880  				} else {
2881  					pattern.lastIndex = 0;
2882
2883  					var match = pattern.exec(str);
2884  				}
2885
2886  				if (!match) {
2887  					if (oneshot) {
2888  						break;
2889  					}
2890
2891  					continue;
2892  				}
2893
2894  				if (lookbehind) {
2895  					lookbehindLength = match[1] ? match[1].length : 0;
2896  				}
2897
2898  				var from = match.index + lookbehindLength,
2899  					match = match[0].slice(lookbehindLength),
2900  					to = from + match.length,
2901  					before = str.slice(0, from),
2902  					after = str.slice(to);
2903
2904  				var removeFrom = currentNode.prev;
2905
2906  				if (before) {
2907  					removeFrom = addAfter(tokenList, removeFrom, before);
2908  					pos += before.length;
2909  				}
2910
2911  				removeRange(tokenList, removeFrom, removeCount);
2912
2913  				var wrapped = new Token(token, inside ? _.tokenize(match, inside) : match, alias, match, greedy);
2914  				currentNode = addAfter(tokenList, removeFrom, wrapped);
2915
2916  				if (after) {
2917  					addAfter(tokenList, currentNode, after);
2918  				}
2919
2920
2921  				if (removeCount > 1)
2922  					matchGrammar(text, tokenList, grammar, currentNode.prev, pos, true, token + ',' + j);
2923
2924  				if (oneshot)
2925  					break;
2926  			}
2927  		}
2928  	}
2929  }
2930
2931  /**
2932   * @typedef LinkedListNode
2933   * @property {T} value
2934   * @property {LinkedListNode<T> | null} prev The previous node.
2935   * @property {LinkedListNode<T> | null} next The next node.
2936   * @template T
2937   */
2938
2939  /**
2940   * @template T
2941   */
2942  function LinkedList() {
2943  	/** @type {LinkedListNode<T>} */
2944  	var head = { value: null, prev: null, next: null };
2945  	/** @type {LinkedListNode<T>} */
2946  	var tail = { value: null, prev: head, next: null };
2947  	head.next = tail;
2948
2949  	/** @type {LinkedListNode<T>} */
2950  	this.head = head;
2951  	/** @type {LinkedListNode<T>} */
2952  	this.tail = tail;
2953  	this.length = 0;
2954  }
2955
2956  /**
2957   * Adds a new node with the given value to the list.
2958   * @param {LinkedList<T>} list
2959   * @param {LinkedListNode<T>} node
2960   * @param {T} value
2961   * @returns {LinkedListNode<T>} The added node.
2962   * @template T
2963   */
2964  function addAfter(list, node, value) {
2965  	// assumes that node != list.tail && values.length >= 0
2966  	var next = node.next;
2967
2968  	var newNode = { value: value, prev: node, next: next };
2969  	node.next = newNode;
2970  	next.prev = newNode;
2971  	list.length++;
2972
2973  	return newNode;
2974  }
2975  /**
2976   * Removes `count` nodes after the given node. The given node will not be removed.
2977   * @param {LinkedList<T>} list
2978   * @param {LinkedListNode<T>} node
2979   * @param {number} count
2980   * @template T
2981   */
2982  function removeRange(list, node, count) {
2983  	var next = node.next;
2984  	for (var i = 0; i < count && next !== list.tail; i++) {
2985  		next = next.next;
2986  	}
2987  	node.next = next;
2988  	next.prev = node;
2989  	list.length -= i;
2990  }
2991  /**
2992   * @param {LinkedList<T>} list
2993   * @returns {T[]}
2994   * @template T
2995   */
2996  function toArray(list) {
2997  	var array = [];
2998  	var node = list.head.next;
2999  	while (node !== list.tail) {
3000  		array.push(node.value);
3001  		node = node.next;
3002  	}
3003  	return array;
3004  }
3005
3006
3007  if (!_self.document) {
3008  	if (!_self.addEventListener) {
3009  		// in Node.js
3010  		return _;
3011  	}
3012
3013  	if (!_.disableWorkerMessageHandler) {
3014  		// In worker
3015  		_self.addEventListener('message', function (evt) {
3016  			var message = JSON.parse(evt.data),
3017  				lang = message.language,
3018  				code = message.code,
3019  				immediateClose = message.immediateClose;
3020
3021  			_self.postMessage(_.highlight(code, _.languages[lang], lang));
3022  			if (immediateClose) {
3023  				_self.close();
3024  			}
3025  		}, false);
3026  	}
3027
3028  	return _;
3029  }
3030
3031  //Get current script and highlight
3032  var script = _.util.currentScript();
3033
3034  if (script) {
3035  	_.filename = script.src;
3036
3037  	if (script.hasAttribute('data-manual')) {
3038  		_.manual = true;
3039  	}
3040  }
3041
3042  function highlightAutomaticallyCallback() {
3043  	if (!_.manual) {
3044  		_.highlightAll();
3045  	}
3046  }
3047
3048  if (!_.manual) {
3049  	// If the document state is "loading", then we'll use DOMContentLoaded.
3050  	// If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
3051  	// DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they
3052  	// might take longer one animation frame to execute which can create a race condition where only some plugins have
3053  	// been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
3054  	// See https://github.com/PrismJS/prism/issues/2102
3055  	var readyState = document.readyState;
3056  	if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {
3057  		document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
3058  	} else {
3059  		if (window.requestAnimationFrame) {
3060  			window.requestAnimationFrame(highlightAutomaticallyCallback);
3061  		} else {
3062  			window.setTimeout(highlightAutomaticallyCallback, 16);
3063  		}
3064  	}
3065  }
3066
3067  return _;
3068
3069  })(_self);
3070
3071  if ( module.exports) {
3072  	module.exports = Prism;
3073  }
3074
3075  // hack for components to work correctly in node.js
3076  if (typeof commonjsGlobal !== 'undefined') {
3077  	commonjsGlobal.Prism = Prism;
3078  }
3079
3080
3081  /* **********************************************
3082       Begin prism-markup.js
3083  ********************************************** */
3084
3085  Prism.languages.markup = {
3086  	'comment': /<!--[\s\S]*?-->/,
3087  	'prolog': /<\?[\s\S]+?\?>/,
3088  	'doctype': {
3089  		pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:(?!<!--)[^"'\]]|"[^"]*"|'[^']*'|<!--[\s\S]*?-->)*\]\s*)?>/i,
3090  		greedy: true
3091  	},
3092  	'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
3093  	'tag': {
3094  		pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>
3094\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,
3095  		greedy: true,
3096  		inside: {
3097  			'tag': {
3098  				pattern: /^<\/?[^\s>\/]+/i,
3099  				inside: {
3100  					'punctuation': /^<\/?/,
3101  					'namespace': /^[^\s>\/:]+:/
3102  				}
3103  			},
3104  			'attr-value': {
3105  				pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i,
3106  				inside: {
3107  					'punctuation': [
3108  						/^=/,
3109  						{
3110  							pattern: /^(\s*)["']|["']$/,
3111  							lookbehind: true
3112  						}
3113  					]
3114  				}
3115  			},
3116  			'punctuation': /\/?>/,
3117  			'attr-name': {
3118  				pattern: /[^\s>\/]+/,
3119  				inside: {
3120  					'namespace': /^[^\s>\/:]+:/
3121  				}
3122  			}
3123
3124  		}
3125  	},
3126  	'entity': /&#?[\da-z]{1,8};/i
3127  };
3128
3129  Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] =
3130  	Prism.languages.markup['entity'];
3131
3132  // Plugin to make entity title show the real entity, idea by Roman Komarov
3133  Prism.hooks.add('wrap', function(env) {
3134
3135  	if (env.type === 'entity') {
3136  		env.attributes['title'] = env.content.replace(/&amp;/, '&');
3137  	}
3138  });
3139
3140  Object.defineProperty(Prism.languages.markup.tag, 'addInlined', {
3141  	/**
3142  	 * Adds an inlined language to markup.
3143  	 *
3144  	 * An example of an inlined language is CSS with `<style>` tags.
3145  	 *
3146  	 * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
3147  	 * case insensitive.
3148  	 * @param {string} lang The language key.
3149  	 * @example
3150  	 * addInlined('style', 'css');
3151  	 */
3152  	value: function addInlined(tagName, lang) {
3153  		var includedCdataInside = {};
3154  		includedCdataInside['language-' + lang] = {
3155  			pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
3156  			lookbehind: true,
3157  			inside: Prism.languages[lang]
3158  		};
3159  		includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i;
3160
3161  		var inside = {
3162  			'included-cdata': {
3163  				pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
3164  				inside: includedCdataInside
3165  			}
3166  		};
3167  		inside['language-' + lang] = {
3168  			pattern: /[\s\S]+/,
3169  			inside: Prism.languages[lang]
3170  		};
3171
3172  		var def = {};
3173  		def[tagName] = {
3174  			pattern: RegExp(/(<__[\s\S]*?>)(?:<!\[CDATA\[[\s\S]*?\]\]>\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g, function () { return tagName; }), 'i'),
3175  			lookbehind: true,
3176  			greedy: true,
3177  			inside: inside
3178  		};
3179
3180  		Prism.languages.insertBefore('markup', 'cdata', def);
3181  	}
3182  });
3183
3184  Prism.languages.xml = Prism.languages.extend('markup', {});
3185  Prism.languages.html = Prism.languages.markup;
3186  Prism.languages.mathml = Prism.languages.markup;
3187  Prism.languages.svg = Prism.languages.markup;
3188
3189
3190  /* **********************************************
3191       Begin prism-css.js
3192  ********************************************** */
3193
3194  (function (Prism) {
3195
3196  	var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;
3197
3198  	Prism.languages.css = {
3199  		'comment': /\/\*[\s\S]*?\*\//,
3200  		'atrule': {
3201  			pattern: /@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,
3202  			inside: {
3203  				'rule': /^@[\w-]+/,
3204  				'selector-function-argument': {
3205  					pattern: /(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,
3206  					lookbehind: true,
3207  					alias: 'selector'
3208  				}
3209  				// See rest below
3210  			}
3211  		},
3212  		'url': {
3213  			pattern: RegExp('url\\((?:' + string.source + '|[^\n\r()]*)\\)', 'i'),
3214  			greedy: true,
3215  			inside: {
3216  				'function': /^url/i,
3217  				'punctuation': /^\(|\)$/
3218  			}
3219  		},
3220  		'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'),
3221  		'string': {
3222  			pattern: string,
3223  			greedy: true
3224  		},
3225  		'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,
3226  		'important': /!important\b/i,
3227  		'function': /[-a-z0-9]+(?=\()/i,
3228  		'punctuation': /[(){};:,]/
3229  	};
3230
3231  	Prism.languages.css['atrule'].inside.rest = Prism.languages.css;
3232
3233  	var markup = Prism.languages.markup;
3234  	if (markup) {
3235  		markup.tag.addInlined('style', 'css');
3236
3237  		Prism.languages.insertBefore('inside', 'attr-value', {
3238  			'style-attr': {
3239  				pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,
3240  				inside: {
3241  					'attr-name': {
3242  						pattern: /^\s*style/i,
3243  						inside: markup.tag.inside
3244  					},
3245  					'punctuation': /^\s*=\s*['"]|['"]\s*$/,
3246  					'attr-value': {
3247  						pattern: /.+/i,
3248  						inside: Prism.languages.css
3249  					}
3250  				},
3251  				alias: 'language-css'
3252  			}
3253  		}, markup.tag);
3254  	}
3255
3256  }(Prism));
3257
3258
3259  /* **********************************************
3260       Begin prism-clike.js
3261  ********************************************** */
3262
3263  Prism.languages.clike = {
3264  	'comment': [
3265  		{
3266  			pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
3267  			lookbehind: true
3268  		},
3269  		{
3270  			pattern: /(^|[^\\:])\/\/.*/,
3271  			lookbehind: true,
3272  			greedy: true
3273  		}
3274  	],
3275  	'string': {
3276  		pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
3277  		greedy: true
3278  	},
3279  	'class-name': {
3280  		pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,
3281  		lookbehind: true,
3282  		inside: {
3283  			'punctuation': /[.\\]/
3284  		}
3285  	},
3286  	'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
3287  	'boolean': /\b(?:true|false)\b/,
3288  	'function': /\w+(?=\()/,
3289  	'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
3290  	'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
3291  	'punctuation': /[{}[\];(),.:]/
3292  };
3293
3294
3295  /* **********************************************
3296       Begin prism-javascript.js
3297  ********************************************** */
3298
3299  Prism.languages.javascript = Prism.languages.extend('clike', {
3300  	'class-name': [
3301  		Prism.languages.clike['class-name'],
3302  		{
3303  			pattern: /(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,
3304  			lookbehind: true
3305  		}
3306  	],
3307  	'keyword': [
3308  		{
3309  			pattern: /((?:^|})\s*)(?:catch|finally)\b/,
3310  			lookbehind: true
3311  		},
3312  		{
3313  			pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
3314  			lookbehind: true
3315  		},
3316  	],
3317  	'number': /\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,
3318  	// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
3319  	'function': /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
3320  	'operator': /--|\+\+|\*\*=?|=>|&&|\|\||[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?[.?]?|[~:]/
3321  });
3322
3323  Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/;
3324
3325  Prism.languages.insertBefore('javascript', 'keyword', {
3326  	'regex': {
3327  		pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*[\s\S]*?\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,
3328  		lookbehind: true,
3329  		greedy: true
3330  	},
3331  	// This must be declared before keyword because we use "function" inside the look-forward
3332  	'function-variable': {
3333  		pattern: /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]
3333*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,
3334  		alias: 'function'
3335  	},
3336  	'parameter': [
3337  		{
3338  			pattern: /(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,
3339  			lookbehind: true,
3340  			inside: Prism.languages.javascript
3341  		},
3342  		{
3343  			pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,
3344  			inside: Prism.languages.javascript
3345  		},
3346  		{
3347  			pattern: /(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,
3348  			lookbehind: true,
3349  			inside: Prism.languages.javascript
3350  		},
3351  		{
3352  			pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,
3353  			lookbehind: true,
3354  			inside: Prism.languages.javascript
3355  		}
3356  	],
3357  	'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/
3358  });
3359
3360  Prism.languages.insertBefore('javascript', 'string', {
3361  	'template-string': {
3362  		pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,
3363  		greedy: true,
3364  		inside: {
3365  			'template-punctuation': {
3366  				pattern: /^`|`$/,
3367  				alias: 'string'
3368  			},
3369  			'interpolation': {
3370  				pattern: /((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,
3371  				lookbehind: true,
3372  				inside: {
3373  					'interpolation-punctuation': {
3374  						pattern: /^\${|}$/,
3375  						alias: 'punctuation'
3376  					},
3377  					rest: Prism.languages.javascript
3378  				}
3379  			},
3380  			'string': /[\s\S]+/
3381  		}
3382  	}
3383  });
3384
3385  if (Prism.languages.markup) {
3386  	Prism.languages.markup.tag.addInlined('script', 'javascript');
3387  }
3388
3389  Prism.languages.js = Prism.languages.javascript;
3390
3391
3392  /* **********************************************
3393       Begin prism-file-highlight.js
3394  ********************************************** */
3395
3396  (function () {
3397  	if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
3398  		return;
3399  	}
3400
3401  	/**
3402  	 * @param {Element} [container=document]
3403  	 */
3404  	self.Prism.fileHighlight = function(container) {
3405  		container = container || document;
3406
3407  		var Extensions = {
3408  			'js': 'javascript',
3409  			'py': 'python',
3410  			'rb': 'ruby',
3411  			'ps1': 'powershell',
3412  			'psm1': 'powershell',
3413  			'sh': 'bash',
3414  			'bat': 'batch',
3415  			'h': 'c',
3416  			'tex': 'latex'
3417  		};
3418
3419  		Array.prototype.slice.call(container.querySelectorAll('pre[data-src]')).forEach(function (pre) {
3420  			// ignore if already loaded
3421  			if (pre.hasAttribute('data-src-loaded')) {
3422  				return;
3423  			}
3424
3425  			// load current
3426  			var src = pre.getAttribute('data-src');
3427
3428  			var language, parent = pre;
3429  			var lang = /\blang(?:uage)?-([\w-]+)\b/i;
3430  			while (parent && !lang.test(parent.className)) {
3431  				parent = parent.parentNode;
3432  			}
3433
3434  			if (parent) {
3435  				language = (pre.className.match(lang) || [, ''])[1];
3436  			}
3437
3438  			if (!language) {
3439  				var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
3440  				language = Extensions[extension] || extension;
3441  			}
3442
3443  			var code = document.createElement('code');
3444  			code.className = 'language-' + language;
3445
3446  			pre.textContent = '';
3447
3448  			code.textContent = 'Loading…';
3449
3450  			pre.appendChild(code);
3451
3452  			var xhr = new XMLHttpRequest();
3453
3454  			xhr.open('GET', src, true);
3455
3456  			xhr.onreadystatechange = function () {
3457  				if (xhr.readyState == 4) {
3458
3459  					if (xhr.status < 400 && xhr.responseText) {
3460  						code.textContent = xhr.responseText;
3461
3462  						Prism.highlightElement(code);
3463  						// mark as loaded
3464  						pre.setAttribute('data-src-loaded', '');
3465  					}
3466  					else if (xhr.status >= 400) {
3467  						code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
3468  					}
3469  					else {
3470  						code.textContent = '✖ Error: File does not exist or is empty';
3471  					}
3472  				}
3473  			};
3474
3475  			xhr.send(null);
3476  		});
3477  	};
3478
3479  	document.addEventListener('DOMContentLoaded', function () {
3480  		// execute inside handler, for dropping Event as argument
3481  		self.Prism.fileHighlight();
3482  	});
3483
3484  })();
3485  });
3486
3487  Prism.languages.python = {
3488  	'comment': {
3489  		pattern: /(^|[^\\])#.*/,
3490  		lookbehind: true
3491  	},
3492  	'string-interpolation': {
3493  		pattern: /(?:f|rf|fr)(?:("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,
3494  		greedy: true,
3495  		inside: {
3496  			'interpolation': {
3497  				// "{" <expression> <optional "!s", "!r", or "!a"> <optional ":" format specifier> "}"
3498  				pattern: /((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,
3499  				lookbehind: true,
3500  				inside: {
3501  					'format-spec': {
3502  						pattern: /(:)[^:(){}]+(?=}$)/,
3503  						lookbehind: true
3504  					},
3505  					'conversion-option': {
3506  						pattern: /![sra](?=[:}]$)/,
3507  						alias: 'punctuation'
3508  					},
3509  					rest: null
3510  				}
3511  			},
3512  			'string': /[\s\S]+/
3513  		}
3514  	},
3515  	'triple-quoted-string': {
3516  		pattern: /(?:[rub]|rb|br)?("""|''')[\s\S]+?\1/i,
3517  		greedy: true,
3518  		alias: 'string'
3519  	},
3520  	'string': {
3521  		pattern: /(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,
3522  		greedy: true
3523  	},
3524  	'function': {
3525  		pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,
3526  		lookbehind: true
3527  	},
3528  	'class-name': {
3529  		pattern: /(\bclass\s+)\w+/i,
3530  		lookbehind: true
3531  	},
3532  	'decorator': {
3533  		pattern: /(^\s*)@\w+(?:\.\w+)*/im,
3534  		lookbehind: true,
3535  		alias: ['annotation', 'punctuation'],
3536  		inside: {
3537  			'punctuation': /\./
3538  		}
3539  	},
3540  	'keyword': /\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
3541  	'builtin': /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,
3542  	'boolean': /\b(?:True|False|None)\b/,
3543  	'number': /(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,
3544  	'operator': /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
3545  	'punctuation': /[{}[\];(),.:]/
3546  };
3547
3548  Prism.languages.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python;
3549
3550  Prism.languages.py = Prism.languages.python;
3551
3552  Prism.languages.clike = {
3553  	'comment': [
3554  		{
3555  			pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
3556  			lookbehind: true
3557  		},
3558  		{
3559  			pattern: /(^|[^\\:])\/\/.*/,
3560  			lookbehind: true,
3561  			greedy: true
3562  		}
3563  	],
3564  	'string': {
3565  		pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
3566  		greedy: true
3567  	},
3568  	'class-name': {
3569  		pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,
3570  		lookbehind: true,
3571  		inside: {
3572  			'punctuation': /[.\\]/
3573  		}
3574  	},
3575  	'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
3576  	'boolean': /\b(?:true|false)\b/,
3577  	'function': /\w+(?=\()/,
3578  	'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
3579  	'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
3580  	'punctuation': /[{}[\];(),.:]/
3581  };
3582
3583  Prism.languages.lua = {
3584  	'comment': /^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,
3585  	// \z may be used to skip the following space
3586  	'string': {
3587  		pattern: /(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[\s\S]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,
3588  		greedy: true
3589  	},
3590  	'number': /\b0x[a-f\d]+\.?[a-f\d]*(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|\.?\d*(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,
3591  	'keyword': /\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,
3592  	'function': /(?!\d)\w+(?=\s*(?:[({]))/,
3593  	'operator': [
3594  		/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,
3595  		{
3596  			// Match ".." but don't break "..."
3597  			pattern: /(^|[^.])\.\.(?!\.)/,
3598  			lookbehind: true
3599  		}
3600  	],
3601  	'punctuation': /[\[\](){},;]|\.+|:+/
3602  };
3603
3604  (function(Prism) {
3605  	// $ set | grep '^[A-Z][^[:space:]]*=' | cut -d= -f1 | tr '\n' '|'
3606  	// + LC_ALL, RANDOM, REPLY, SECONDS.
3607  	// + make sure PS1..4 are here as they are not always set,
3608  	// - some useless things.
3609  	var envVars = '\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_
3609CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b';
3610  	var insideString = {
3611  		'environment': {
3612  			pattern: RegExp("\\$" + envVars),
3613  			alias: 'constant'
3614  		},
3615  		'variable': [
3616  			// [0]: Arithmetic Environment
3617  			{
3618  				pattern: /\$?\(\([\s\S]+?\)\)/,
3619  				greedy: true,
3620  				inside: {
3621  					// If there is a $ sign at the beginning highlight $(( and )) as variable
3622  					'variable': [
3623  						{
3624  							pattern: /(^\$\(\([\s\S]+)\)\)/,
3625  							lookbehind: true
3626  						},
3627  						/^\$\(\(/
3628  					],
3629  					'number': /\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/,
3630  					// Operators according to https://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic
3631  					'operator': /--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,
3632  					// If there is no $ sign at the beginning highlight (( and )) as punctuation
3633  					'punctuation': /\(\(?|\)\)?|,|;/
3634  				}
3635  			},
3636  			// [1]: Command Substitution
3637  			{
3638  				pattern: /\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,
3639  				greedy: true,
3640  				inside: {
3641  					'variable': /^\$\(|^`|\)$|`$/
3642  				}
3643  			},
3644  			// [2]: Brace expansion
3645  			{
3646  				pattern: /\$\{[^}]+\}/,
3647  				greedy: true,
3648  				inside: {
3649  					'operator': /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,
3650  					'punctuation': /[\[\]]/,
3651  					'environment': {
3652  						pattern: RegExp("(\\{)" + envVars),
3653  						lookbehind: true,
3654  						alias: 'constant'
3655  					}
3656  				}
3657  			},
3658  			/\$(?:\w+|[#?*!@$])/
3659  		],
3660  		// Escape sequences from echo and printf's manuals, and escaped quotes.
3661  		'entity': /\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/
3662  	};
3663
3664  	Prism.languages.bash = {
3665  		'shebang': {
3666  			pattern: /^#!\s*\/.*/,
3667  			alias: 'important'
3668  		},
3669  		'comment': {
3670  			pattern: /(^|[^"{\\$])#.*/,
3671  			lookbehind: true
3672  		},
3673  		'function-name': [
3674  			// a) function foo {
3675  			// b) foo() {
3676  			// c) function foo() {
3677  			// but not “foo {”
3678  			{
3679  				// a) and c)
3680  				pattern: /(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/,
3681  				lookbehind: true,
3682  				alias: 'function'
3683  			},
3684  			{
3685  				// b)
3686  				pattern: /\b\w+(?=\s*\(\s*\)\s*\{)/,
3687  				alias: 'function'
3688  			}
3689  		],
3690  		// Highlight variable names as variables in for and select beginnings.
3691  		'for-or-select': {
3692  			pattern: /(\b(?:for|select)\s+)\w+(?=\s+in\s)/,
3693  			alias: 'variable',
3694  			lookbehind: true
3695  		},
3696  		// Highlight variable names as variables in the left-hand part
3697  		// of assignments (“=” and “+=”).
3698  		'assign-left': {
3699  			pattern: /(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,
3700  			inside: {
3701  				'environment': {
3702  					pattern: RegExp("(^|[\\s;|&]|[<>]\\()" + envVars),
3703  					lookbehind: true,
3704  					alias: 'constant'
3705  				}
3706  			},
3707  			alias: 'variable',
3708  			lookbehind: true
3709  		},
3710  		'string': [
3711  			// Support for Here-documents https://en.wikipedia.org/wiki/Here_document
3712  			{
3713  				pattern: /((?:^|[^<])<<-?\s*)(\w+?)\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\2/,
3714  				lookbehind: true,
3715  				greedy: true,
3716  				inside: insideString
3717  			},
3718  			// Here-document with quotes around the tag
3719  			// → No expansion (so no “inside”).
3720  			{
3721  				pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\3/,
3722  				lookbehind: true,
3723  				greedy: true
3724  			},
3725  			// “Normal” string
3726  			{
3727  				pattern: /(^|[^\\](?:\\\\)*)(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\2)[^\\])*\2/,
3728  				lookbehind: true,
3729  				greedy: true,
3730  				inside: insideString
3731  			}
3732  		],
3733  		'environment': {
3734  			pattern: RegExp("\\$?" + envVars),
3735  			alias: 'constant'
3736  		},
3737  		'variable': insideString.variable,
3738  		'function': {
3739  			pattern: /(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|
3739ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,
3740  			lookbehind: true
3741  		},
3742  		'keyword': {
3743  			pattern: /(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,
3744  			lookbehind: true
3745  		},
3746  		// https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html
3747  		'builtin': {
3748  			pattern: /(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,
3749  			lookbehind: true,
3750  			// Alias added to make those easier to distinguish from strings.
3751  			alias: 'class-name'
3752  		},
3753  		'boolean': {
3754  			pattern: /(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,
3755  			lookbehind: true
3756  		},
3757  		'file-descriptor': {
3758  			pattern: /\B&\d\b/,
3759  			alias: 'important'
3760  		},
3761  		'operator': {
3762  			// Lots of redirections here, but not just that.
3763  			pattern: /\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/,
3764  			inside: {
3765  				'file-descriptor': {
3766  					pattern: /^\d/,
3767  					alias: 'important'
3768  				}
3769  			}
3770  		},
3771  		'punctuation': /\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,
3772  		'number': {
3773  			pattern: /(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,
3774  			lookbehind: true
3775  		}
3776  	};
3777
3778  	/* Patterns in command substitution. */
3779  	var toBeCopied = [
3780  		'comment',
3781  		'function-name',
3782  		'for-or-select',
3783  		'assign-left',
3784  		'string',
3785  		'environment',
3786  		'function',
3787  		'keyword',
3788  		'builtin',
3789  		'boolean',
3790  		'file-descriptor',
3791  		'operator',
3792  		'punctuation',
3793  		'number'
3794  	];
3795  	var inside = insideString.variable[1].inside;
3796  	for(var i = 0; i < toBeCopied.length; i++) {
3797  		inside[toBeCopied[i]] = Prism.languages.bash[toBeCopied[i]];
3798  	}
3799
3800  	Prism.languages.shell = Prism.languages.bash;
3801  })(Prism);
3802
3803  Prism.languages.go = Prism.languages.extend('clike', {
3804  	'keyword': /\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,
3805  	'builtin': /\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/,
3806  	'boolean': /\b(?:_|iota|nil|true|false)\b/,
3807  	'operator': /[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,
3808  	'number': /(?:\b0x[a-f\d]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[-+]?\d+)?)i?/i,
3809  	'string': {
3810  		pattern: /(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,
3811  		greedy: true
3812  	}
3813  });
3814  delete Prism.languages.go['class-name'];
3815
3816  (function (Prism) {
3817
3818  	// Allow only one line break
3819  	var inner = /(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?!\n|\r\n?))/.source;
3820
3821  	/**
3822  	 * This function is intended for the creation of the bold or italic pattern.
3823  	 *
3824  	 * This also adds a lookbehind group to the given pattern to ensure that the pattern is not backslash-escaped.
3825  	 *
3826  	 * _Note:_ Keep in mind that this adds a capturing group.
3827  	 *
3828  	 * @param {string} pattern
3829  	 * @param {boolean} starAlternative Whether to also add an alternative where all `_`s are replaced with `*`s.
3830  	 * @returns {RegExp}
3831  	 */
3832  	function createInline(pattern, starAlternative) {
3833  		pattern = pattern.replace(/<inner>/g, function () { return inner; });
3834  		if (starAlternative) {
3835  			pattern = pattern + '|' + pattern.replace(/_/g, '\\*');
3836  		}
3837  		return RegExp(/((?:^|[^\\])(?:\\{2}
3837)*)/.source + '(?:' + pattern + ')');
3838  	}
3839
3840
3841  	var tableCell = /(?:\\.|``.+?``|`[^`\r\n]+`|[^\\|\r\n`])+/.source;
3842  	var tableRow = /\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|$)/.source.replace(/__/g, function () { return tableCell; });
3843  	var tableLine = /\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;
3844
3845
3846  	Prism.languages.markdown = Prism.languages.extend('markup', {});
3847  	Prism.languages.insertBefore('markdown', 'prolog', {
3848  		'blockquote': {
3849  			// > ...
3850  			pattern: /^>(?:[\t ]*>)*/m,
3851  			alias: 'punctuation'
3852  		},
3853  		'table': {
3854  			pattern: RegExp('^' + tableRow + tableLine + '(?:' + tableRow + ')*', 'm'),
3855  			inside: {
3856  				'table-data-rows': {
3857  					pattern: RegExp('^(' + tableRow + tableLine + ')(?:' + tableRow + ')*$'),
3858  					lookbehind: true,
3859  					inside: {
3860  						'table-data': {
3861  							pattern: RegExp(tableCell),
3862  							inside: Prism.languages.markdown
3863  						},
3864  						'punctuation': /\|/
3865  					}
3866  				},
3867  				'table-line': {
3868  					pattern: RegExp('^(' + tableRow + ')' + tableLine + '$'),
3869  					lookbehind: true,
3870  					inside: {
3871  						'punctuation': /\||:?-{3,}:?/
3872  					}
3873  				},
3874  				'table-header-row': {
3875  					pattern: RegExp('^' + tableRow + '$'),
3876  					inside: {
3877  						'table-header': {
3878  							pattern: RegExp(tableCell),
3879  							alias: 'important',
3880  							inside: Prism.languages.markdown
3881  						},
3882  						'punctuation': /\|/
3883  					}
3884  				}
3885  			}
3886  		},
3887  		'code': [
3888  			{
3889  				// Prefixed by 4 spaces or 1 tab and preceded by an empty line
3890  				pattern: /((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,
3891  				lookbehind: true,
3892  				alias: 'keyword'
3893  			},
3894  			{
3895  				// `code`
3896  				// ``code``
3897  				pattern: /``.+?``|`[^`\r\n]+`/,
3898  				alias: 'keyword'
3899  			},
3900  			{
3901  				// ```optional language
3902  				// code block
3903  				// ```
3904  				pattern: /^```[\s\S]*?^```$/m,
3905  				greedy: true,
3906  				inside: {
3907  					'code-block': {
3908  						pattern: /^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,
3909  						lookbehind: true
3910  					},
3911  					'code-language': {
3912  						pattern: /^(```).+/,
3913  						lookbehind: true
3914  					},
3915  					'punctuation': /```/
3916  				}
3917  			}
3918  		],
3919  		'title': [
3920  			{
3921  				// title 1
3922  				// =======
3923
3924  				// title 2
3925  				// -------
3926  				pattern: /\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,
3927  				alias: 'important',
3928  				inside: {
3929  					punctuation: /==+$|--+$/
3930  				}
3931  			},
3932  			{
3933  				// # title 1
3934  				// ###### title 6
3935  				pattern: /(^\s*)#+.+/m,
3936  				lookbehind: true,
3937  				alias: 'important',
3938  				inside: {
3939  					punctuation: /^#+|#+$/
3940  				}
3941  			}
3942  		],
3943  		'hr': {
3944  			// ***
3945  			// ---
3946  			// * * *
3947  			// -----------
3948  			pattern: /(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,
3949  			lookbehind: true,
3950  			alias: 'punctuation'
3951  		},
3952  		'list': {
3953  			// * item
3954  			// + item
3955  			// - item
3956  			// 1. item
3957  			pattern: /(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,
3958  			lookbehind: true,
3959  			alias: 'punctuation'
3960  		},
3961  		'url-reference': {
3962  			// [id]: http://example.com "Optional title"
3963  			// [id]: http://example.com 'Optional title'
3964  			// [id]: http://example.com (Optional title)
3965  			// [id]: <http://example.com> "Optional title"
3966  			pattern: /!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,
3967  			inside: {
3968  				'variable': {
3969  					pattern: /^(!?\[)[^\]]+/,
3970  					lookbehind: true
3971  				},
3972  				'string': /(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,
3973  				'punctuation': /^[\[\]!:]|[<>]/
3974  			},
3975  			alias: 'url'
3976  		},
3977  		'bold': {
3978  			// **strong**
3979  			// __strong__
3980
3981  			// allow one nested instance of italic text using the same delimiter
3982  			pattern: createInline(/__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__/.source, true),
3983  			lookbehind: true,
3984  			greedy: true,
3985  			inside: {
3986  				'content': {
3987  					pattern: /(^..)[\s\S]+(?=..$)/,
3988  					lookbehind: true,
3989  					inside: {} // see below
3990  				},
3991  				'punctuation': /\*\*|__/
3992  			}
3993  		},
3994  		'italic': {
3995  			// *em*
3996  			// _em_
3997
3998  			// allow one nested instance of bold text using the same delimiter
3999  			pattern: createInline(/_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_/.source, true),
4000  			lookbehind: true,
4001  			greedy: true,
4002  			inside: {
4003  				'content': {
4004  					pattern: /(^.)[\s\S]+(?=.$)/,
4005  					lookbehind: true,
4006  					inside: {} // see below
4007  				},
4008  				'punctuation': /[*_]/
4009  			}
4010  		},
4011  		'strike': {
4012  			// ~~strike through~~
4013  			// ~strike~
4014  			pattern: createInline(/(~~?)(?:(?!~)<inner>)+?\2/.source, false),
4015  			lookbehind: true,
4016  			greedy: true,
4017  			inside: {
4018  				'content': {
4019  					pattern: /(^~~?)[\s\S]+(?=\1$)/,
4020  					lookbehind: true,
4021  					inside: {} // see below
4022  				},
4023  				'punctuation': /~~?/
4024  			}
4025  		},
4026  		'url': {
4027  			// [example](http://example.com "Optional title")
4028  			// [example][id]
4029  			// [example] [id]
4030  			pattern: createInline(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[(?:(?!\])<inner>)+\])/.source, false),
4031  			lookbehind: true,
4032  			greedy: true,
4033  			inside: {
4034  				'variable': {
4035  					pattern: /(\[)[^\]]+(?=\]$)/,
4036  					lookbehind: true
4037  				},
4038  				'content': {
4039  					pattern: /(^!?\[)[^\]]+(?=\])/,
4040  					lookbehind: true,
4041  					inside: {} // see below
4042  				},
4043  				'string': {
4044  					pattern: /"(?:\\.|[^"\\])*"(?=\)$)/
4045  				}
4046  			}
4047  		}
4048  	});
4049
4050  	['url', 'bold', 'italic', 'strike'].forEach(function (token) {
4051  		['url', 'bold', 'italic', 'strike'].forEach(function (inside) {
4052  			if (token !== inside) {
4053  				Prism.languages.markdown[token].inside.content.inside[inside] = Prism.languages.markdown[inside];
4054  			}
4055  		});
4056  	});
4057
4058  	Prism.hooks.add('after-tokenize', function (env) {
4059  		if (env.language !== 'markdown' && env.language !== 'md') {
4060  			return;
4061  		}
4062
4063  		function walkTokens(tokens) {
4064  			if (!tokens || typeof tokens === 'string') {
4065  				return;
4066  			}
4067
4068  			for (var i = 0, l = tokens.length; i < l; i++) {
4069  				var token = tokens[i];
4070
4071  				if (token.type !== 'code') {
4072  					walkTokens(token.content);
4073  					continue;
4074  				}
4075
4076  				/*
4077  				 * Add the correct `language-xxxx` class to this code block. Keep in mind that the `code-language` token
4078  				 * is optional. But the grammar is defined so that there is only one case we have to handle:
4079  				 *
4080  				 * token.content = [
4081  				 *     <span class="punctuation">```</span>,
4082  				 *     <span class="code-language">xxxx</span>,
4083  				 *     '\n', // exactly one new lines (\r or \n or \r\n)
4084  				 *     <span class="code-block">...</span>,
4085  				 *     '\n', // exactly one new lines again
4086  				 *     <span class="punctuation">```</span>
4087  				 * ];
4088  				 */
4089
4090  				var codeLang = token.content[1];
4091  				var codeBlock = token.content[3];
4092
4093  				if (codeLang && codeBlock &&
4094  					codeLang.type === 'code-language' && codeBlock.type === 'code-block' &&
4095  					typeof codeLang.content === 'string') {
4096
4097  					// this might be a language that Prism does not support
4098
4099  					// do some replacements to support C++, C#, and F#
4100  					var lang = codeLang.content.replace(/\b#/g, 'sharp').replace(/\b\+\+/g, 'pp');
4101  					// only use the first word
4102  					lang = (/[a-z][\w-]*/i.exec(lang) || [''])[0].toLowerCase();
4103  					var alias = 'language-' + lang;
4104
4105  					// add alias
4106  					if (!codeBlock.alias) {
4107  						codeBlock.alias = [alias];
4108  					} else if (typeof codeBlock.alias === 'string') {
4109  						codeBlock.alias = [codeBlock.alias, alias];
4110  					} else {
4111  						codeBlock.alias.push(alias);
4112  					}
4113  				}
4114  			}
4115  		}
4116
4117  		walkTokens(env.tokens);
4118  	});
4119
4120  	Prism.hooks.add('wrap', function (env) {
4121  		if (env.type !== 'code-block') {
4122  			return;
4123  		}
4124
4125  		var codeLang = '';
4126  		for (var i = 0, l = env.classes.length; i < l; i++) {
4127  			var cls = env.classes[i];
4128  			var match = /language-(.+)/.exec(cls);
4129  			if (match) {
4130  				codeLang = match[1];
4131  				break;
4132  			}
4133  		}
4134
4135  		var grammar = Prism.languages[codeLang];
4136
4137  		if (!grammar) {
4138  			if (codeLang && codeLang !== 'none' && Prism.plugins.autoloader) {
4139  				var id = 'md-' + new Date().valueOf() + '-' + Math.floor(Math.random() * 1e16);
4140  				env.attributes['id'] = id;
4141
4142  				Prism.plugins.autoloader.loadLanguages(codeLang, function () {
4143  					var ele = document.getElementById(id);
4144  					if (ele) {
4145  						ele.innerHTML = Prism.highlight(ele.textContent, Prism.languages[codeLang], codeLang);
4146  					}
4147  				});
4148  			}
4149  		} else {
4150  			// reverse Prism.util.encode
4151  			var code = env.content.replace(/&lt;/g, '<').replace(/&amp;/g, '&');
4152
4153  			env.content = Prism.highlight(code, grammar, codeLang);
4154  		}
4155  	});
4156
4157  	Prism.languages.md = Prism.languages.markdown;
4158
4159  }(Prism));
4160
4161  Prism.languages.julia= {
4162  	'comment': {
4163  		pattern: /(^|[^\\])#.*/,
4164  		lookbehind: true
4165  	},
4166  	'string': /("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2/,
4167  	'keyword' : /\b(?:abstract|baremodule|begin|bitstype|break|catch|ccall|const|continue|do|else|elseif|end|export|finally|for|function|global|if|immutable|import|importall|in|let|local|macro|module|print|println|quote|return|struct|try|type|typealias|using|while)\b/,
4168  	'boolean' : /\b(?:true|false)\b/,
4169  	'number' : /(?:\b(?=\d)|\B(?=\.))(?:0[box])?(?:[\da-f]+\.?\d*|\.\d+)(?:[efp][+-]?\d+)?j?/i,
4170  	'operator': /[-+*^%÷&$\\]=?|\/[\/=]?|!=?=?|\|[=>]?|<(?:<=?|[=:])?|>(?:=|>>?=?)?|==?=?|[~≠≤≥]/,
4171  	'punctuation' : /[{}[\];(),.:]/,
4172  	'constant': /\b(?:(?:NaN|Inf)(?:16|32|64)?)\b/
4173  };
4174
4175  var css = "/**\n * prism.js default theme for JavaScript, CSS and HTML\n * Based on dabblet (http://dabblet.com)\n * @author Lea Verou\n */\n\ncode[class*=\"language-\"],\npre[class*=\"language-\"] {\n\tcolor: black;\n\tbackground: none;\n\ttext-shadow: 0 1px white;\n\tfont-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n\tfont-size: 1em;\n\ttext-align: left;\n\twhite-space: pre;\n\tword-spacing: normal;\n\tword-break: normal;\n\tword-wrap: normal;\n\tline-height: 1.5;\n\n\t-moz-tab-size: 4;\n\t-o-tab-size: 4;\n\ttab-size: 4;\n\n\t-webkit-hyphens: none;\n\t-moz-hyphens: none;\n\t-ms-hyphens: none;\n\thyphens: none;\n}\n\npre[class*=\"language-\"]::-moz-selection, pre[class*=\"language-\"] ::-moz-selection,\ncode[class*=\"language-\"]::-moz-selection, code[class*=\"language-\"] ::-moz-selection {\n\ttext-shadow: none;\n\tbackground: #b3d4fc;\n}\n\npre[class*=\"language-\"]::selection, pre[class*=\"language-\"] ::selection,\ncode[class*=\"language-\"]::selection, code[class*=\"language-\"] ::selection {\n\ttext-shadow: none;\n\tbackground: #b3d4fc;\n}\n\n@media print {\n\tcode[class*=\"language-\"],\n\tpre[class*=\"language-\"] {\n\t\ttext-shadow: none;\n\t}\n}\n\n/* Code blocks */\npre[class*=\"language-\"] {\n\tpadding: 1em;\n\tmargin: .5em 0;\n\toverflow: auto;\n}\n\n:not(pre) > code[class*=\"language-\"],\npre[class*=\"language-\"] {\n\tbackground: #f5f2f0;\n}\n\n/* Inline code */\n:not(pre) > code[class*=\"language-\"] {\n\tpadding: .1em;\n\tborder-radius: .3em;\n\twhite-space: normal;\n}\n\n.token.comment,\n.token.prolog,\n.token.doctype,\n.token.cdata {\n\tcolor: slategray;\n}\n\n.token.punctuation {\n\tcolor: #999;\n}\n\n.token.namespace {\n\topacity: .7;\n}\n\n.token.property,\n.token.tag,\n.token.boolean,\n.token.number,\n.token.constant,\n.token.symbol,\n.token.deleted {\n\tcolor: #905;\n}\n\n.token.selector,\n.token.attr-name,\n.token.string,\n.token.char,\n.token.builtin,\n.token.inserted {\n\tcolor: #690;\n}\n\n.token.operator,\n.token.entity,\n.token.url,\n.language-css .token.string,\n.style .token.string {\n\tcolor: #9a6e3a;\n\tbackground: hsla(0, 0%, 100%, .5);\n}\n\n.token.atrule,\n.token.attr-value,\n.token.keyword {\n\tcolor: #07a;\n}\n\n.token.function,\n.token.class-name {\n\tcolor: #DD4A68;\n}\n\n.token.regex,\n.token.important,\n.token.variable {\n\tcolor: #e90;\n}\n\n.token.important,\n.token.bold {\n\tfont-weight: bold;\n}\n.token.italic {\n\tfont-style: italic;\n}\n\n.token.entity {\n\tcursor: help;\n}\n";
4176
4177  // Copyright 2018 The Distill Template Authors
4178
4179  const T$4 = Template('d-code', `
4180<style>
4181
4182code {
4183  white-space: nowrap;
4184  background: rgba(0, 0, 0, 0.04);
4185  border-radius: 2px;
4186  padding: 4px 7px;
4187  font-size: 15px;
4188  color: rgba(0, 0, 0, 0.6);
4189}
4190
4191pre code {
4192  display: block;
4193  border-left: 2px solid rgba(0, 0, 0, .1);
4194  padding: 0 0 0 36px;
4195}
4196
4197${css}
4198</style>
4199
4200<code id="code-container"></code>
4201
4202`);
4203
4204  class Code extends Mutating(T$4(HTMLElement)) {
4205
4206    renderContent() {
4207
4208      // check if language can be highlighted
4209      this.languageName = this.getAttribute('language');
4210      if (!this.languageName) {
4211        console.warn('You need to provide a language attribute to your <d-code>
4211 block to let us know how to highlight your code; e.g.:\n <d-code language="python">zeros = np.zeros(shape)</d-code>.');
4212        return;
4213      }
4214      const language = prism.languages[this.languageName];
4215      if (language == undefined) {
4216        console.warn(`Distill does not yet support highlighting your code block in "${this.languageName}'.`);
4217        return;
4218      }
4219
4220      let content = this.textContent;
4221      const codeTag = this.shadowRoot.querySelector('#code-container');
4222
4223      if (this.hasAttribute('block')) {
4224        // normalize the tab indents
4225        content = content.replace(/\n/, '');
4226        const tabs = content.match(/\s*/);
4227        content = content.replace(new RegExp('\n' + tabs, 'g'), '\n');
4228        content = content.trim();
4229        // wrap code block in pre tag if needed
4230        if (codeTag.parentNode instanceof ShadowRoot) {
4231          const preTag = document.createElement('pre');
4232          this.shadowRoot.removeChild(codeTag);
4233          preTag.appendChild(codeTag);
4234          this.shadowRoot.appendChild(preTag);
4235        }
4236
4237      }
4238
4239      codeTag.className = `language-${this.languageName}`;
4240      codeTag.innerHTML = prism.highlight(content, language);
4241    }
4242
4243  }
4244
4245  // Copyright 2018 The Distill Template Authors
4246
4247  const T$5 = Template('d-footnote', `
4248<style>
4249
4250d-math[block] {
4251  display: block;
4252}
4253
4254:host {
4255
4256}
4257
4258sup {
4259  line-height: 1em;
4260  font-size: 0.75em;
4261  position: relative;
4262  top: -.5em;
4263  vertical-align: baseline;
4264}
4265
4266span {
4267  color: hsla(206, 90%, 20%, 0.7);
4268  cursor: default;
4269}
4270
4271.footnote-container {
4272  padding: 10px;
4273}
4274
4275</style>
4276
4277<d-hover-box>
4278  <div class="footnote-container">
4279    <slot id="slot"></slot>
4280  </div>
4281</d-hover-box>
4282
4283<sup>
4284  <span id="fn-" data-hover-ref=""></span>
4285</sup>
4286
4287`);
4288
4289  class Footnote extends T$5(HTMLElement) {
4290
4291    constructor() {
4292      super();
4293
4294      const options = {childList: true, characterData: true, subtree: true};
4295      const observer = new MutationObserver(this.notify);
4296      observer.observe(this, options);
4297    }
4298
4299    notify() {
4300      const options = { detail: this, bubbles: true };
4301      const event = new CustomEvent('onFootnoteChanged', options);
4302      document.dispatchEvent(event);
4303    }
4304
4305    connectedCallback() {
4306      // listen and notify about changes to slotted content
4307      // const slot = this.shadowRoot.querySelector('#slot');
4308      // console.warn(slot.textContent);
4309      // slot.addEventListener('slotchange', this.notify);
4310      this.hoverBox = this.root.querySelector('d-hover-box');
4311      window.customElements.whenDefined('d-hover-box').then(() => {
4312        this.hoverBox.listen(this);
4313      });
4314      // create numeric ID
4315      Footnote.currentFootnoteId += 1;
4316      const IdString = Footnote.currentFootnoteId.toString();
4317      this.root.host.id = 'd-footnote-' + IdString;
4318
4319      // set up hidden hover box
4320      const id = 'dt-fn-hover-box-' + IdString;
4321      this.hoverBox.id = id;
4322
4323      // set up visible footnote marker
4324      const span = this.root.querySelector('#fn-');
4325      span.setAttribute('id', 'fn-' + IdString);
4326      span.setAttribute('data-hover-ref', id);
4327      span.textContent = IdString;
4328    }
4329
4330  }
4331
4332  Footnote.currentFootnoteId = 0;
4333
4334  // Copyright 2018 The Distill Template Authors
4335
4336  const T$6 = Template('d-footnote-list', `
4337<style>
4338
4339d-footnote-list {
4340  contain: layout style;
4341}
4342
4343d-footnote-list > * {
4344  grid-column: text;
4345}
4346
4347d-footnote-list a.footnote-backlink {
4348  color: rgba(0,0,0,0.3);
4349  padding-left: 0.5em;
4350}
4351
4352</style>
4353
4354<h3>Footnotes</h3>
4355<ol></ol>
4356`, false);
4357
4358  class FootnoteList extends T$6(HTMLElement) {
4359
4360    connectedCallback() {
4361      super.connectedCallback();
4362
4363      this.list = this.root.querySelector('ol');
4364      // footnotes list is initially hidden
4365      this.root.style.display = 'none';
4366      // look through document and register existing footnotes
4367      // Store.subscribeTo('footnotes', (footnote) => {
4368      //   this.renderFootnote(footnote);
4369      // });
4370    }
4371
4372    // TODO: could optimize this to accept individual footnotes?
4373    set footnotes(footnotes) {
4374      this.list.innerHTML = '';
4375      if (footnotes.length) {
4376        // ensure footnote list is visible
4377        this.root.style.display = '';
4378
4379        for (const footnote of footnotes) {
4380          // construct and append list item to show footnote
4381          const listItem = document.createElement('li');
4382          listItem.id = footnote.id + '-listing';
4383          listItem.innerHTML = footnote.innerHTML;
4384
4385          const backlink = document.createElement('a');
4386          backlink.setAttribute('class', 'footnote-backlink');
4387          backlink.textContent = '[↩]';
4388          backlink.href = '#' + footnote.id;
4389
4390          listItem.appendChild(backlink);
4391          this.list.appendChild(listItem);
4392        }
4393      } else {
4394        // ensure footnote list is invisible
4395        this.root.style.display = 'none';
4396      }
4397    }
4398
4399  }
4400
4401  // Copyright 2018 The Distill Template Authors
4402
4403  const T$7 = Template('d-hover-box', `
4404<style>
4405
4406:host {
4407  position: absolute;
4408  width: 100%;
4409  left: 0px;
4410  z-index: 10000;
4411  display: none;
4412  white-space: normal
4413}
4414
4415.container {
4416  position: relative;
4417  width: 704px;
4418  max-width: 100vw;
4419  margin: 0 auto;
4420}
4421
4422.panel {
4423  position: absolute;
4424  font-size: 1rem;
4425  line-height: 1.5em;
4426  top: 0;
4427  left: 0;
4428  width: 100%;
4429  border: 1px solid rgba(0, 0, 0, 0.1);
4430  background-color: rgba(250, 250, 250, 0.95);
4431  box-shadow: 0 0 7px rgba(0, 0, 0, 0.1);
4432  border-radius: 4px;
4433  box-sizing: border-box;
4434
4435  backdrop-filter: blur(2px);
4436  -webkit-backdrop-filter: blur(2px);
4437}
4438
4439</style>
4440
4441<div class="container">
4442  <div class="panel">
4443    <slot></slot>
4444  </div>
4445</div>
4446`);
4447
4448  class HoverBox extends T$7(HTMLElement) {
4449
4450    constructor() {
4451      super();
4452    }
4453
4454    connectedCallback() {
4455
4456    }
4457
4458    listen(element) {
4459      // console.log(element)
4460      this.bindDivEvents(this);
4461      this.bindTriggerEvents(element);
4462      // this.style.display = "block";
4463    }
4464
4465    bindDivEvents(element) {
4466      // For mice, same behavior as hovering on links
4467      element.addEventListener('mouseover', () => {
4468        if (!this.visible) this.showAtNode(element);
4469        this.stopTimeout();
4470      });
4471      element.addEventListener('mouseout', () => {
4472        this.extendTimeout(500);
4473      });
4474      // Don't trigger body touchstart event when touching within box
4475      element.addEventListener('touchstart', (event) => {
4476        event.stopPropagation();
4477      }, {passive: true});
4478      // Close box when touching outside box
4479      document.body.addEventListener('touchstart', () => {
4480        this.hide();
4481      }, {passive: true});
4482    }
4483
4484    bindTriggerEvents(node) {
4485      node.addEventListener('mouseover', () => {
4486        if (!this.visible) {
4487          this.showAtNode(node);
4488        }
4489        this.stopTimeout();
4490      });
4491
4492      node.addEventListener('mouseout', () => {
4493        this.extendTimeout(300);
4494      });
4495
4496      node.addEventListener('touchstart', (event) => {
4497        if (this.visible) {
4498          this.hide();
4499        } else {
4500          this.showAtNode(node);
4501        }
4502        // Don't trigger body touchstart event when touching link
4503        event.stopPropagation();
4504      }, {passive: true});
4505    }
4506
4507    show(position) {
4508      this.visible = true;
4509      this.style.display = 'block';
4510      // 10px extra offset from element
4511      this.style.top = Math.round(position[1] + 10) + 'px';
4512    }
4513
4514    showAtNode(node) {
4515      // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop
4516      const bbox = node.getBoundingClientRect();
4517      this.show([node.offsetLeft + bbox.width, node.offsetTop + bbox.height]);
4518    }
4519
4520    hide() {
4521      this.visible = false;
4522      this.style.display = 'none';
4523      this.stopTimeout();
4524    }
4525
4526    stopTimeout() {
4527      if (this.timeout) {
4528        clearTimeout(this.timeout);
4529      }
4530    }
4531
4532    extendTimeout(time) {
4533      this.stopTimeout();
4534      this.timeout = setTimeout(() => {
4535        this.hide();
4536      }, time);
4537    }
4538
4539  }
4540
4541  // Copyright 2018 The Distill Template Authors
4542  //
4543  // Licensed under the Apache License, Version 2.0 (the "License");
4544  // you may not use this file except in compliance with the License.
4545  // You may obtain a copy of the License at
4546  //
4547  //      http://www.apache.org/licenses/LICENSE-2.0
4548  //
4549  // Unless required by applicable law or agreed to in writing, software
4550  // distributed under the License is distributed on an "AS IS" BASIS,
4551  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4552  // See the License for the specific language governing permissions and
4553  // limitations under the License.
4554
4555  class Title extends HTMLElement {
4556    static get is() { return 'd-title'; }
4557  }
4558
4559  // Copyright 2018 The Distill Template Authors
4560
4561  const T$8 = Template('d-references', `
4562<style>
4563d-references {
4564  display: block;
4565}
4566</style>
4567`, false);
4568
4569  class References extends T$8(HTMLElement) {
4570
4571  }
4572
4573  // Copyright 2018 The Distill Template Authors
4574  //
4575  // Licensed under the Apache License, Version 2.0 (the "License");
4576  // you may not use this file except in compliance with the License.
4577  // You may obtain a copy of the License at
4578  //
4579  //      http://www.apache.org/licenses/LICENSE-2.0
4580  //
4581  // Unless required by applicable law or agreed to in writing, software
4582  // distributed under the License is distributed on an "AS IS" BASIS,
4583  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4584  // See the License for the specific language governing permissions and
4585  // limitations under the License.
4586
4587  class TOC extends HTMLElement {
4588
4589    static get is() { return 'd-toc'; }
4590
4591    connectedCallback() {
4592      if (!this.getAttribute('prerendered')) {
4593        window.onload = () => {
4594          const article = document.querySelector('d-article');
4595          const headings = article.querySelectorAll('h2, h3');
4596          renderTOC(this, headings);
4597        };
4598      }
4599    }
4600
4601  }
4602
4603  function renderTOC(element, headings) {
4604
4605    let ToC =`
4606  <style>
4607
4608  d-toc {
4609    contain: layout style;
4610    display: block;
4611  }
4612
4613  d-toc ul {
4614    padding-left: 0;
4615  }
4616
4617  d-toc ul > ul {
4618    padding-left: 24px;
4619  }
4620
4621  d-toc a {
4622    border-bottom: none;
4623    text-decoration: none;
4624  }
4625
4626  </style>
4627  <nav role="navigation" class="table-of-contents"></nav>
4628  <h2>Table of contents</h2>
4629  <ul>`;
4630
4631    for (const el of headings) {
4632      // should element be included in TOC?
4633      const isInTitle = el.parentElement.tagName == 'D-TITLE';
4634      const isException = el.getAttribute('no-toc');
4635      if (isInTitle || isException) continue;
4636      // create TOC entry
4637      const title = el.textContent;
4638      const link = '#' + el.getAttribute('id');
4639
4640      let newLine = '<li>' + '<a href="' + link + '">' + title + '</a>' + '</li>';
4641      if (el.tagName == 'H3') {
4642        newLine = '<ul>' + newLine + '</ul>';
4643      } else {
4644        newLine += '<br>';
4645      }
4646      ToC += newLine;
4647
4648    }
4649
4650    ToC += '</ul></nav>';
4651    element.innerHTML = ToC;
4652  }
4653
4654  // Copyright 2018 The Distill Template Authors
4655  //
4656  // Licensed under the Apache License, Version 2.0 (the "License");
4657  // you may not use this file except in compliance with the License.
4658  // You may obtain a copy of the License at
4659  //
4660  //      http://www.apache.org/licenses/LICENSE-2.0
4661  //
4662  // Unless required by applicable law or agreed to in writing, software
4663  // distributed under the License is distributed on an "AS IS" BASIS,
4664  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4665  // See the License for the specific language governing permissions and
4666  // limitations under the License.
4667
4668  // Figure
4669  //
4670  // d-figure provides a state-machine of visibility events:
4671  //
4672  //                         scroll out of view
4673  //                         +----------------+
4674  //   *do work here*        |                |
4675  // +----------------+    +-+---------+    +-v---------+
4676  // | ready          +----> onscreen  |    | offscreen |
4677  // +----------------+    +---------^-+    +---------+-+
4678  //                                 |                |
4679  //                                 +----------------+
4680  //                                  scroll into view
4681  //
4682
4683  class Figure extends HTMLElement {
4684
4685    static get is() { return 'd-figure'; }
4686
4687    static get readyQueue() {
4688      if (!Figure._readyQueue) {
4689        Figure._readyQueue = [];
4690      }
4691      return Figure._readyQueue;
4692    }
4693
4694    static addToReadyQueue(figure) {
4695      if (Figure.readyQueue.indexOf(figure) === -1) {
4696        Figure.readyQueue.push(figure);
4697        Figure.runReadyQueue();
4698      }
4699    }
4700
4701    static runReadyQueue() {
4702      // console.log("Checking to run readyQueue, length: " + Figure.readyQueue.length + ", scrolling: " + Figure.isScrolling);
4703      // if (Figure.isScrolling) return;
4704      // console.log("Running ready Queue");
4705      const figure = Figure.readyQueue
4706        .sort((a,b) => a._seenOnScreen - b._seenOnScreen )
4707        .filter((figure) => !figure._ready)
4708        .pop();
4709      if (figure) {
4710        figure.ready();
4711        requestAnimationFrame(Figure.runReadyQueue);
4712      }
4713
4714    }
4715
4716    constructor() {
4717      super();
4718      // debugger
4719      this._ready = false;
4720      this._onscreen = false;
4721      this._offscreen = true;
4722    }
4723
4724    connectedCallback() {
4725      this.loadsWhileScrolling = this.hasAttribute('loadsWhileScrolling');
4726      Figure.marginObserver.observe(this);
4727      Figure.directObserver.observe(this);
4728    }
4729
4730    disconnectedCallback() {
4731      Figure.marginObserver.unobserve(this);
4732      Figure.directObserver.unobserve(this);
4733    }
4734
4735    // We use two separate observers:
4736    // One with an extra 1000px margin to warn if the viewpoint gets close,
4737    // And one for the actual on/off screen events
4738
4739    static get marginObserver() {
4740      if (!Figure._marginObserver) {
4741        // if (!('IntersectionObserver' in window)) {
4742        //   throw new Error('no interscetionobbserver!');
4743        // }
4744        const viewportHeight = window.innerHeight;
4745        const margin = Math.floor(2 * viewportHeight);
4746        const options = {rootMargin: margin + 'px 0px ' + margin + 'px 0px', threshold: 0.01};
4747        const callback = Figure.didObserveMarginIntersection;
4748        const observer = new IntersectionObserver(callback, options);
4749        Figure._marginObserver = observer;
4750      }
4751      return Figure._marginObserver;
4752    }
4753
4754    static didObserveMarginIntersection(entries) {
4755      for (const entry of entries) {
4756        const figure = entry.target;
4757        if (entry.isIntersecting && !figure._ready) {
4758          Figure.addToReadyQueue(figure);
4759        }
4760      }
4761    }
4762
4763    static get directObserver() {
4764      if (!Figure._directObserver) {
4765        Figure._directObserver = new IntersectionObserver(
4766          Figure.didObserveDirectIntersection, {
4767            rootMargin: '0px', threshold: [0, 1.0],
4768          }
4769        );
4770      }
4771      return Figure._directObserver;
4772    }
4773
4774    static didObserveDirectIntersection(entries) {
4775      for (const entry of entries) {
4776        const figure = entry.target;
4777        if (entry.isIntersecting) {
4778          figure._seenOnScreen = new Date();
4779          // if (!figure._ready) { figure.ready(); }
4780          if (figure._offscreen) { figure.onscreen(); }
4781        } else {
4782          if (figure._onscreen) { figure.offscreen(); }
4783        }
4784      }
4785    }
4786
4787    // Notify listeners that registered late, too:
4788
4789    addEventListener(eventName, callback) {
4790      super.addEventListener(eventName, callback);
4791      // if we had already dispatched something while presumingly no one was listening, we do so again
4792      // debugger
4793      if (eventName === 'ready') {
4794        if (Figure.readyQueue.indexOf(this) !== -1) {
4795          this._ready = false;
4796          Figure.runReadyQueue();
4797        }
4798      }
4799      if (eventName === 'onscreen') {
4800        this.onscreen();
4801      }
4802    }
4803
4804    // Custom Events
4805
4806    ready() {
4807      // debugger
4808      this._ready = true;
4809      Figure.marginObserver.unobserve(this);
4810      const event = new CustomEvent('ready');
4811      this.dispatchEvent(event);
4812    }
4813
4814    onscreen() {
4815      this._onscreen = true;
4816      this._offscreen = false;
4817      const event = new CustomEvent('onscreen');
4818      this.dispatchEvent(event);
4819    }
4820
4821    offscreen() {
4822      this._onscreen = false;
4823      this._offscreen = true;
4824      const event = new CustomEvent('offscreen');
4825      this.dispatchEvent(event);
4826    }
4827
4828  }
4829
4830  if (typeof window !== 'undefined') {
4831
4832    Figure.isScrolling = false;
4833    let timeout;
4834    const resetTimer = () => {
4835      Figure.isScrolling = true;
4836      clearTimeout(timeout);
4837      timeout = setTimeout(() => {
4838        Figure.isScrolling = false;
4839        Figure.runReadyQueue();
4840      }, 500);
4841    };
4842    window.addEventListener('scroll', resetTimer, true);
4843
4844  }
4845
4846  // Copyright 2018 The Distill Template Authors
4847
4848  // This overlay is not secure.
4849  // It is only meant as a social deterrent.
4850
4851  const productionHostname = 'distill.pub';
4852  const T$9 = Template('d-interstitial', `
4853<style>
4854
4855.overlay {
4856  position: fixed;
4857  width: 100%;
4858  height: 100%;
4859  top: 0;
4860  left: 0;
4861  background: white;
4862
4863  opacity: 1;
4864  visibility: visible;
4865
4866  display: flex;
4867  flex-flow: column;
4868  justify-content: center;
4869  z-index: 2147483647 /* MaxInt32 */
4870
4871}
4872
4873.container {
4874  position: relative;
4875  margin-left: auto;
4876  margin-right: auto;
4877  max-width: 420px;
4878  padding: 2em;
4879}
4880
4881h1 {
4882  text-decoration: underline;
4883  text-decoration-color: hsl(0,100%,40%);
4884  -webkit-text-decoration-color: hsl(0,100%,40%);
4885  margin-bottom: 1em;
4886  line-height: 1.5em;
4887}
4888
4889input[type="password"] {
4890  -webkit-appearance: none;
4891  -moz-appearance: none;
4892  appearance: none;
4893  -webkit-box-shadow: none;
4894  -moz-box-shadow: none;
4895  box-shadow: none;
4896  -webkit-border-radius: none;
4897  -moz-border-radius: none;
4898  -ms-border-radius: none;
4899  -o-border-radius: none;
4900  border-radius: none;
4901  outline: none;
4902
4903  font-size: 18px;
4904  background: none;
4905  width: 25%;
4906  padding: 10px;
4907  border: none;
4908  border-bottom: solid 2px #999;
4909  transition: border .3s;
4910}
4911
4912input[type="password"]:focus {
4913  border-bottom: solid 2px #333;
4914}
4915
4916input[type="password"].wrong {
4917  border-bottom: solid 2px hsl(0,100%,40%);
4918}
4919
4920p small {
4921  color: #888;
4922}
4923
4924.logo {
4925  position: relative;
4926  font-size: 1.5em;
4927  margin-bottom: 3em;
4928}
4929
4930.logo svg {
4931  width: 36px;
4932  position: relative;
4933  top: 6px;
4934  margin-right: 2px;
4935}
4936
4937.logo svg path {
4938  fill: none;
4939  stroke: black;
4940  stroke-width: 2px;
4941}
4942
4943</style>
4944
4945<div class="overlay">
4946  <div class="container">
4947    <h1>This article is in review.</h1>
4948    <p>
4948Do not share this URL or the contents of this article. Thank you!</p>
4949    <input id="interstitial-password-input" type="password" name="password" autofocus/>
4950    <p><small>Enter the password we shared with you as part of the review process to view the article.</small></p>
4951  </div>
4952</div>
4953`);
4954
4955  class Interstitial extends T$9(HTMLElement) {
4956
4957    connectedCallback() {
4958      if (this.shouldRemoveSelf()) {
4959        this.parentElement.removeChild(this);
4960      } else {
4961        const passwordInput = this.root.querySelector('#interstitial-password-input');
4962        passwordInput.oninput = (event) => this.passwordChanged(event);
4963      }
4964    }
4965
4966    passwordChanged(event) {
4967      const entered = event.target.value;
4968      if (entered === this.password) {
4969        console.log('Correct password entered.');
4970        this.parentElement.removeChild(this);
4971        if (typeof(Storage) !== 'undefined') {
4972          console.log('Saved that correct password was entered.');
4973          localStorage.setItem(this.localStorageIdentifier(), 'true');
4974        }
4975      }
4976    }
4977
4978    shouldRemoveSelf() {
4979      // should never be visible in production
4980      if (window && window.location.hostname === productionHostname) {
4981        console.warn('Interstitial found on production, hiding it.');
4982        return true
4983      }
4984      // should only have to enter password once
4985      if (typeof(Storage) !== 'undefined') {
4986        if (localStorage.getItem(this.localStorageIdentifier()) === 'true') {
4987          console.log('Loaded that correct password was entered before; skipping interstitial.');
4988          return true;
4989        }
4990      }
4991      // otherwise, leave visible
4992      return false;
4993    }
4994
4995    localStorageIdentifier() {
4996      const prefix = 'distill-drafts';
4997      const suffix = 'interstitial-password-correct';
4998      return prefix + (window ? window.location.pathname : '-') + suffix
4999    }
5000
5001  }
5002
5003  function ascending(a, b) {
5004    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
5005  }
5006
5007  function bisector(compare) {
5008    if (compare.length === 1) compare = ascendingComparator(compare);
5009    return {
5010      left: function(a, x, lo, hi) {
5011        if (lo == null) lo = 0;
5012        if (hi == null) hi = a.length;
5013        while (lo < hi) {
5014          var mid = lo + hi >>> 1;
5015          if (compare(a[mid], x) < 0) lo = mid + 1;
5016          else hi = mid;
5017        }
5018        return lo;
5019      },
5020      right: function(a, x, lo, hi) {
5021        if (lo == null) lo = 0;
5022        if (hi == null) hi = a.length;
5023        while (lo < hi) {
5024          var mid = lo + hi >>> 1;
5025          if (compare(a[mid], x) > 0) hi = mid;
5026          else lo = mid + 1;
5027        }
5028        return lo;
5029      }
5030    };
5031  }
5032
5033  function ascendingComparator(f) {
5034    return function(d, x) {
5035      return ascending(f(d), x);
5036    };
5037  }
5038
5039  var ascendingBisect = bisector(ascending);
5040  var bisectRight = ascendingBisect.right;
5041
5042  function range(start, stop, step) {
5043    start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
5044
5045    var i = -1,
5046        n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
5047        range = new Array(n);
5048
5049    while (++i < n) {
5050      range[i] = start + i * step;
5051    }
5052
5053    return range;
5054  }
5055
5056  var e10 = Math.sqrt(50),
5057      e5 = Math.sqrt(10),
5058      e2 = Math.sqrt(2);
5059
5060  function ticks(start, stop, count) {
5061    var reverse,
5062        i = -1,
5063        n,
5064        ticks,
5065        step;
5066
5067    stop = +stop, start = +start, count = +count;
5068    if (start === stop && count > 0) return [start];
5069    if (reverse = stop < start) n = start, start = stop, stop = n;
5070    if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
5071
5072    if (step > 0) {
5073      start = Math.ceil(start / step);
5074      stop = Math.floor(stop / step);
5075      ticks = new Array(n = Math.ceil(stop - start + 1));
5076      while (++i < n) ticks[i] = (start + i) * step;
5077    } else {
5078      start = Math.floor(start * step);
5079      stop = Math.ceil(stop * step);
5080      ticks = new Array(n = Math.ceil(start - stop + 1));
5081      while (++i < n) ticks[i] = (start - i) / step;
5082    }
5083
5084    if (reverse) ticks.reverse();
5085
5086    return ticks;
5087  }
5088
5089  function tickIncrement(start, stop, count) {
5090    var step = (stop - start) / Math.max(0, count),
5091        power = Math.floor(Math.log(step) / Math.LN10),
5092        error = step / Math.pow(10, power);
5093    return power >= 0
5094        ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power)
5095        : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
5096  }
5097
5098  function tickStep(start, stop, count) {
5099    var step0 = Math.abs(stop - start) / Math.max(0, count),
5100        step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
5101        error = step0 / step1;
5102    if (error >= e10) step1 *= 10;
5103    else if (error >= e5) step1 *= 5;
5104    else if (error >= e2) step1 *= 2;
5105    return stop < start ? -step1 : step1;
5106  }
5107
5108  function initRange(domain, range) {
5109    switch (arguments.length) {
5110      case 0: break;
5111      case 1: this.range(domain); break;
5112      default: this.range(range).domain(domain); break;
5113    }
5114    return this;
5115  }
5116
5117  function define(constructor, factory, prototype) {
5118    constructor.prototype = factory.prototype = prototype;
5119    prototype.constructor = constructor;
5120  }
5121
5122  function extend(parent, definition) {
5123    var prototype = Object.create(parent.prototype);
5124    for (var key in definition) prototype[key] = definition[key];
5125    return prototype;
5126  }
5127
5128  function Color() {}
5129
5130  var darker = 0.7;
5131  var brighter = 1 / darker;
5132
5133  var reI = "\\s*([+-]?\\d+)\\s*",
5134      reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
5135      reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
5136      reHex = /^#([0-9a-f]{3,8})$/,
5137      reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
5138      reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
5139      reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
5140      reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
5141      reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
5142      reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
5143
5144  var named = {
vendor: 4,355 bytes, lines 5145-5322
5145    aliceblue: 0xf0f8ff,
5146    antiquewhite: 0xfaebd7,
5147    aqua: 0x00ffff,
5148    aquamarine: 0x7fffd4,
5149    azure: 0xf0ffff,
5150    beige: 0xf5f5dc,
5151    bisque: 0xffe4c4,
5152    black: 0x000000,
5153    blanchedalmond: 0xffebcd,
5154    blue: 0x0000ff,
5155    blueviolet: 0x8a2be2,
5156    brown: 0xa52a2a,
5157    burlywood: 0xdeb887,
5158    cadetblue: 0x5f9ea0,
5159    chartreuse: 0x7fff00,
5160    chocolate: 0xd2691e,
5161    coral: 0xff7f50,
5162    cornflowerblue: 0x6495ed,
5163    cornsilk: 0xfff8dc,
5164    crimson: 0xdc143c,
5165    cyan: 0x00ffff,
5166    darkblue: 0x00008b,
5167    darkcyan: 0x008b8b,
5168    darkgoldenrod: 0xb8860b,
5169    darkgray: 0xa9a9a9,
5170    darkgreen: 0x006400,
5171    darkgrey: 0xa9a9a9,
5172    darkkhaki: 0xbdb76b,
5173    darkmagenta: 0x8b008b,
5174    darkolivegreen: 0x556b2f,
5175    darkorange: 0xff8c00,
5176    darkorchid: 0x9932cc,
5177    darkred: 0x8b0000,
5178    darksalmon: 0xe9967a,
5179    darkseagreen: 0x8fbc8f,
5180    darkslateblue: 0x483d8b,
5181    darkslategray: 0x2f4f4f,
5182    darkslategrey: 0x2f4f4f,
5183    darkturquoise: 0x00ced1,
5184    darkviolet: 0x9400d3,
5185    deeppink: 0xff1493,
5186    deepskyblue: 0x00bfff,
5187    dimgray: 0x696969,
5188    dimgrey: 0x696969,
5189    dodgerblue: 0x1e90ff,
5190    firebrick: 0xb22222,
5191    floralwhite: 0xfffaf0,
5192    forestgreen: 0x228b22,
5193    fuchsia: 0xff00ff,
5194    gainsboro: 0xdcdcdc,
5195    ghostwhite: 0xf8f8ff,
5196    gold: 0xffd700,
5197    goldenrod: 0xdaa520,
5198    gray: 0x808080,
5199    green: 0x008000,
5200    greenyellow: 0xadff2f,
5201    grey: 0x808080,
5202    honeydew: 0xf0fff0,
5203    hotpink: 0xff69b4,
5204    indianred: 0xcd5c5c,
5205    indigo: 0x4b0082,
5206    ivory: 0xfffff0,
5207    khaki: 0xf0e68c,
5208    lavender: 0xe6e6fa,
5209    lavenderblush: 0xfff0f5,
5210    lawngreen: 0x7cfc00,
5211    lemonchiffon: 0xfffacd,
5212    lightblue: 0xadd8e6,
5213    lightcoral: 0xf08080,
5214    lightcyan: 0xe0ffff,
5215    lightgoldenrodyellow: 0xfafad2,
5216    lightgray: 0xd3d3d3,
5217    lightgreen: 0x90ee90,
5218    lightgrey: 0xd3d3d3,
5219    lightpink: 0xffb6c1,
5220    lightsalmon: 0xffa07a,
5221    lightseagreen: 0x20b2aa,
5222    lightskyblue: 0x87cefa,
5223    lightslategray: 0x778899,
5224    lightslategrey: 0x778899,
5225    lightsteelblue: 0xb0c4de,
5226    lightyellow: 0xffffe0,
5227    lime: 0x00ff00,
5228    limegreen: 0x32cd32,
5229    linen: 0xfaf0e6,
5230    magenta: 0xff00ff,
5231    maroon: 0x800000,
5232    mediumaquamarine: 0x66cdaa,
5233    mediumblue: 0x0000cd,
5234    mediumorchid: 0xba55d3,
5235    mediumpurple: 0x9370db,
5236    mediumseagreen: 0x3cb371,
5237    mediumslateblue: 0x7b68ee,
5238    mediumspringgreen: 0x00fa9a,
5239    mediumturquoise: 0x48d1cc,
5240    mediumvioletred: 0xc71585,
5241    midnightblue: 0x191970,
5242    mintcream: 0xf5fffa,
5243    mistyrose: 0xffe4e1,
5244    moccasin: 0xffe4b5,
5245    navajowhite: 0xffdead,
5246    navy: 0x000080,
5247    oldlace: 0xfdf5e6,
5248    olive: 0x808000,
5249    olivedrab: 0x6b8e23,
5250    orange: 0xffa500,
5251    orangered: 0xff4500,
5252    orchid: 0xda70d6,
5253    palegoldenrod: 0xeee8aa,
5254    palegreen: 0x98fb98,
5255    paleturquoise: 0xafeeee,
5256    palevioletred: 0xdb7093,
5257    papayawhip: 0xffefd5,
5258    peachpuff: 0xffdab9,
5259    peru: 0xcd853f,
5260    pink: 0xffc0cb,
5261    plum: 0xdda0dd,
5262    powderblue: 0xb0e0e6,
5263    purple: 0x800080,
5264    rebeccapurple: 0x663399,
5265    red: 0xff0000,
5266    rosybrown: 0xbc8f8f,
5267    royalblue: 0x4169e1,
5268    saddlebrown: 0x8b4513,
5269    salmon: 0xfa8072,
5270    sandybrown: 0xf4a460,
5271    seagreen: 0x2e8b57,
5272    seashell: 0xfff5ee,
5273    sienna: 0xa0522d,
5274    silver: 0xc0c0c0,
5275    skyblue: 0x87ceeb,
5276    slateblue: 0x6a5acd,
5277    slategray: 0x708090,
5278    slategrey: 0x708090,
5279    snow: 0xfffafa,
5280    springgreen: 0x00ff7f,
5281    steelblue: 0x4682b4,
5282    tan: 0xd2b48c,
5283    teal: 0x008080,
5284    thistle: 0xd8bfd8,
5285    tomato: 0xff6347,
5286    turquoise: 0x40e0d0,
5287    violet: 0xee82ee,
5288    wheat: 0xf5deb3,
5289    white: 0xffffff,
5290    whitesmoke: 0xf5f5f5,
5291    yellow: 0xffff00,
5292    yellowgreen: 0x9acd32
5293  };
5294
5295  define(Color, color, {
5296    copy: function(channels) {
5297      return Object.assign(new this.constructor, this, channels);
5298    },
5299    displayable: function() {
5300      return this.rgb().displayable();
5301    },
5302    hex: color_formatHex, // Deprecated! Use color.formatHex.
5303    formatHex: color_formatHex,
5304    formatHsl: color_formatHsl,
5305    formatRgb: color_formatRgb,
5306    toString: color_formatRgb
5307  });
5308
5309  function color_formatHex() {
5310    return this.rgb().formatHex();
5311  }
5312
5313  function color_formatHsl() {
5314    return hslConvert(this).formatHsl();
5315  }
5316
5317  function color_formatRgb() {
5318    return this.rgb().formatRgb();
5319  }
5320
5321  function color(format) {
5322    var m, l;
vendor: 5,833 bytes, lines 5323-5484
5323    format = (format + "").trim().toLowerCase();
5324    return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
5325        : l === 3 ? new Rgb((m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1) // #f00
5326        : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
5327        : l === 4 ? rgba((m >> 12 & 0xf) | (m >> 8 & 0xf0), (m >> 8 & 0xf) | (m >> 4 & 0xf0), (m >> 4 & 0xf) | (m & 0xf0), (((m & 0xf) << 4) | (m & 0xf)) / 0xff) // #f000
5328        : null) // invalid hex
5329        : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
5330        : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
5331        : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
5332        : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
5333        : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
5334        : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
5335        : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
5336        : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
5337        : null;
5338  }
5339
5340  function rgbn(n) {
5341    return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
5342  }
5343
5344  function rgba(r, g, b, a) {
5345    if (a <= 0) r = g = b = NaN;
5346    return new Rgb(r, g, b, a);
5347  }
5348
5349  function rgbConvert(o) {
5350    if (!(o instanceof Color)) o = color(o);
5351    if (!o) return new Rgb;
5352    o = o.rgb();
5353    return new Rgb(o.r, o.g, o.b, o.opacity);
5354  }
5355
5356  function rgb(r, g, b, opacity) {
5357    return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
5358  }
5359
5360  function Rgb(r, g, b, opacity) {
5361    this.r = +r;
5362    this.g = +g;
5363    this.b = +b;
5364    this.opacity = +opacity;
5365  }
5366
5367  define(Rgb, rgb, extend(Color, {
5368    brighter: function(k) {
5369      k = k == null ? brighter : Math.pow(brighter, k);
5370      return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
5371    },
5372    darker: function(k) {
5373      k = k == null ? darker : Math.pow(darker, k);
5374      return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
5375    },
5376    rgb: function() {
5377      return this;
5378    },
5379    displayable: function() {
5380      return (-0.5 <= this.r && this.r < 255.5)
5381          && (-0.5 <= this.g && this.g < 255.5)
5382          && (-0.5 <= this.b && this.b < 255.5)
5383          && (0 <= this.opacity && this.opacity <= 1);
5384    },
5385    hex: rgb_formatHex, // Deprecated! Use color.formatHex.
5386    formatHex: rgb_formatHex,
5387    formatRgb: rgb_formatRgb,
5388    toString: rgb_formatRgb
5389  }));
5390
5391  function rgb_formatHex() {
5392    return "#" + hex(this.r) + hex(this.g) + hex(this.b);
5393  }
5394
5395  function rgb_formatRgb() {
5396    var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
5397    return (a === 1 ? "rgb(" : "rgba(")
5398        + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
5399        + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
5400        + Math.max(0, Math.min(255, Math.round(this.b) || 0))
5401        + (a === 1 ? ")" : ", " + a + ")");
5402  }
5403
5404  function hex(value) {
5405    value = Math.max(0, Math.min(255, Math.round(value) || 0));
5406    return (value < 16 ? "0" : "") + value.toString(16);
5407  }
5408
5409  function hsla(h, s, l, a) {
5410    if (a <= 0) h = s = l = NaN;
5411    else if (l <= 0 || l >= 1) h = s = NaN;
5412    else if (s <= 0) h = NaN;
5413    return new Hsl(h, s, l, a);
5414  }
5415
5416  function hslConvert(o) {
5417    if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
5418    if (!(o instanceof Color)) o = color(o);
5419    if (!o) return new Hsl;
5420    if (o instanceof Hsl) return o;
5421    o = o.rgb();
5422    var r = o.r / 255,
5423        g = o.g / 255,
5424        b = o.b / 255,
5425        min = Math.min(r, g, b),
5426        max = Math.max(r, g, b),
5427        h = NaN,
5428        s = max - min,
5429        l = (max + min) / 2;
5430    if (s) {
5431      if (r === max) h = (g - b) / s + (g < b) * 6;
5432      else if (g === max) h = (b - r) / s + 2;
5433      else h = (r - g) / s + 4;
5434      s /= l < 0.5 ? max + min : 2 - max - min;
5435      h *= 60;
5436    } else {
5437      s = l > 0 && l < 1 ? 0 : h;
5438    }
5439    return new Hsl(h, s, l, o.opacity);
5440  }
5441
5442  function hsl(h, s, l, opacity) {
5443    return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
5444  }
5445
5446  function Hsl(h, s, l, opacity) {
5447    this.h = +h;
5448    this.s = +s;
5449    this.l = +l;
5450    this.opacity = +opacity;
5451  }
5452
5453  define(Hsl, hsl, extend(Color, {
5454    brighter: function(k) {
5455      k = k == null ? brighter : Math.pow(brighter, k);
5456      return new Hsl(this.h, this.s, this.l * k, this.opacity);
5457    },
5458    darker: function(k) {
5459      k = k == null ? darker : Math.pow(darker, k);
5460      return new Hsl(this.h, this.s, this.l * k, this.opacity);
5461    },
5462    rgb: function() {
5463      var h = this.h % 360 + (this.h < 0) * 360,
5464          s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
5465          l = this.l,
5466          m2 = l + (l < 0.5 ? l : 1 - l) * s,
5467          m1 = 2 * l - m2;
5468      return new Rgb(
5469        hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
5470        hsl2rgb(h, m1, m2),
5471        hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
5472        this.opacity
5473      );
5474    },
5475    displayable: function() {
5476      return (0 <= this.s && this.s <= 1 || isNaN(this.s))
5477          && (0 <= this.l && this.l <= 1)
5478          && (0 <= this.opacity && this.opacity <= 1);
5479    },
5480    formatHsl: function() {
5481      var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
5482      return (a === 1 ? "hsl(" : "hsla(")
5483          + (this.h || 0) + ", "
5484          + (this.s || 0) * 100 + "%, "
vendor: 17,998 bytes, lines 5485-6113
5485          + (this.l || 0) * 100 + "%"
5486          + (a === 1 ? ")" : ", " + a + ")");
5487    }
5488  }));
5489
5490  /* From FvD 13.37, CSS Color Module Level 3 */
5491  function hsl2rgb(h, m1, m2) {
5492    return (h < 60 ? m1 + (m2 - m1) * h / 60
5493        : h < 180 ? m2
5494        : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
5495        : m1) * 255;
5496  }
5497
5498  var deg2rad = Math.PI / 180;
5499  var rad2deg = 180 / Math.PI;
5500
5501  // https://observablehq.com/@mbostock/lab-and-rgb
5502  var K = 18,
5503      Xn = 0.96422,
5504      Yn = 1,
5505      Zn = 0.82521,
5506      t0 = 4 / 29,
5507      t1 = 6 / 29,
5508      t2 = 3 * t1 * t1,
5509      t3 = t1 * t1 * t1;
5510
5511  function labConvert(o) {
5512    if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
5513    if (o instanceof Hcl) return hcl2lab(o);
5514    if (!(o instanceof Rgb)) o = rgbConvert(o);
5515    var r = rgb2lrgb(o.r),
5516        g = rgb2lrgb(o.g),
5517        b = rgb2lrgb(o.b),
5518        y = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x, z;
5519    if (r === g && g === b) x = z = y; else {
5520      x = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn);
5521      z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn);
5522    }
5523    return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
5524  }
5525
5526  function lab(l, a, b, opacity) {
5527    return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
5528  }
5529
5530  function Lab(l, a, b, opacity) {
5531    this.l = +l;
5532    this.a = +a;
5533    this.b = +b;
5534    this.opacity = +opacity;
5535  }
5536
5537  define(Lab, lab, extend(Color, {
5538    brighter: function(k) {
5539      return new Lab(this.l + K * (k == null ? 1 : k), this.a, this.b, this.opacity);
5540    },
5541    darker: function(k) {
5542      return new Lab(this.l - K * (k == null ? 1 : k), this.a, this.b, this.opacity);
5543    },
5544    rgb: function() {
5545      var y = (this.l + 16) / 116,
5546          x = isNaN(this.a) ? y : y + this.a / 500,
5547          z = isNaN(this.b) ? y : y - this.b / 200;
5548      x = Xn * lab2xyz(x);
5549      y = Yn * lab2xyz(y);
5550      z = Zn * lab2xyz(z);
5551      return new Rgb(
5552        lrgb2rgb( 3.1338561 * x - 1.6168667 * y - 0.4906146 * z),
5553        lrgb2rgb(-0.9787684 * x + 1.9161415 * y + 0.0334540 * z),
5554        lrgb2rgb( 0.0719453 * x - 0.2289914 * y + 1.4052427 * z),
5555        this.opacity
5556      );
5557    }
5558  }));
5559
5560  function xyz2lab(t) {
5561    return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
5562  }
5563
5564  function lab2xyz(t) {
5565    return t > t1 ? t * t * t : t2 * (t - t0);
5566  }
5567
5568  function lrgb2rgb(x) {
5569    return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
5570  }
5571
5572  function rgb2lrgb(x) {
5573    return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
5574  }
5575
5576  function hclConvert(o) {
5577    if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
5578    if (!(o instanceof Lab)) o = labConvert(o);
5579    if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0 < o.l && o.l < 100 ? 0 : NaN, o.l, o.opacity);
5580    var h = Math.atan2(o.b, o.a) * rad2deg;
5581    return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
5582  }
5583
5584  function hcl(h, c, l, opacity) {
5585    return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
5586  }
5587
5588  function Hcl(h, c, l, opacity) {
5589    this.h = +h;
5590    this.c = +c;
5591    this.l = +l;
5592    this.opacity = +opacity;
5593  }
5594
5595  function hcl2lab(o) {
5596    if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity);
5597    var h = o.h * deg2rad;
5598    return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
5599  }
5600
5601  define(Hcl, hcl, extend(Color, {
5602    brighter: function(k) {
5603      return new Hcl(this.h, this.c, this.l + K * (k == null ? 1 : k), this.opacity);
5604    },
5605    darker: function(k) {
5606      return new Hcl(this.h, this.c, this.l - K * (k == null ? 1 : k), this.opacity);
5607    },
5608    rgb: function() {
5609      return hcl2lab(this).rgb();
5610    }
5611  }));
5612
5613  var A = -0.14861,
5614      B = +1.78277,
5615      C = -0.29227,
5616      D = -0.90649,
5617      E = +1.97294,
5618      ED = E * D,
5619      EB = E * B,
5620      BC_DA = B * C - D * A;
5621
5622  function cubehelixConvert(o) {
5623    if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
5624    if (!(o instanceof Rgb)) o = rgbConvert(o);
5625    var r = o.r / 255,
5626        g = o.g / 255,
5627        b = o.b / 255,
5628        l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
5629        bl = b - l,
5630        k = (E * (g - l) - C * bl) / D,
5631        s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
5632        h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
5633    return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
5634  }
5635
5636  function cubehelix(h, s, l, opacity) {
5637    return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
5638  }
5639
5640  function Cubehelix(h, s, l, opacity) {
5641    this.h = +h;
5642    this.s = +s;
5643    this.l = +l;
5644    this.opacity = +opacity;
5645  }
5646
5647  define(Cubehelix, cubehelix, extend(Color, {
5648    brighter: function(k) {
5649      k = k == null ? brighter : Math.pow(brighter, k);
5650      return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
5651    },
5652    darker: function(k) {
5653      k = k == null ? darker : Math.pow(darker, k);
5654      return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
5655    },
5656    rgb: function() {
5657      var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
5658          l = +this.l,
5659          a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
5660          cosh = Math.cos(h),
5661          sinh = Math.sin(h);
5662      return new Rgb(
5663        255 * (l + a * (A * cosh + B * sinh)),
5664        255 * (l + a * (C * cosh + D * sinh)),
5665        255 * (l + a * (E * cosh)),
5666        this.opacity
5667      );
5668    }
5669  }));
5670
5671  function constant(x) {
5672    return function() {
5673      return x;
5674    };
5675  }
5676
5677  function linear(a, d) {
5678    return function(t) {
5679      return a + t * d;
5680    };
5681  }
5682
5683  function exponential(a, b, y) {
5684    return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
5685      return Math.pow(a + t * b, y);
5686    };
5687  }
5688
5689  function gamma(y) {
5690    return (y = +y) === 1 ? nogamma : function(a, b) {
5691      return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a);
5692    };
5693  }
5694
5695  function nogamma(a, b) {
5696    var d = b - a;
5697    return d ? linear(a, d) : constant(isNaN(a) ? b : a);
5698  }
5699
5700  var rgb$1 = (function rgbGamma(y) {
5701    var color = gamma(y);
5702
5703    function rgb$1(start, end) {
5704      var r = color((start = rgb(start)).r, (end = rgb(end)).r),
5705          g = color(start.g, end.g),
5706          b = color(start.b, end.b),
5707          opacity = nogamma(start.opacity, end.opacity);
5708      return function(t) {
5709        start.r = r(t);
5710        start.g = g(t);
5711        start.b = b(t);
5712        start.opacity = opacity(t);
5713        return start + "";
5714      };
5715    }
5716
5717    rgb$1.gamma = rgbGamma;
5718
5719    return rgb$1;
5720  })(1);
5721
5722  function numberArray(a, b) {
5723    if (!b) b = [];
5724    var n = a ? Math.min(b.length, a.length) : 0,
5725        c = b.slice(),
5726        i;
5727    return function(t) {
5728      for (i = 0; i < n; ++i) c[i] = a[i] * (1 - t) + b[i] * t;
5729      return c;
5730    };
5731  }
5732
5733  function isNumberArray(x) {
5734    return ArrayBuffer.isView(x) && !(x instanceof DataView);
5735  }
5736
5737  function genericArray(a, b) {
5738    var nb = b ? b.length : 0,
5739        na = a ? Math.min(nb, a.length) : 0,
5740        x = new Array(na),
5741        c = new Array(nb),
5742        i;
5743
5744    for (i = 0; i < na; ++i) x[i] = interpolate(a[i], b[i]);
5745    for (; i < nb; ++i) c[i] = b[i];
5746
5747    return function(t) {
5748      for (i = 0; i < na; ++i) c[i] = x[i](t);
5749      return c;
5750    };
5751  }
5752
5753  function date(a, b) {
5754    var d = new Date;
5755    return a = +a, b = +b, function(t) {
5756      return d.setTime(a * (1 - t) + b * t), d;
5757    };
5758  }
5759
5760  function interpolateNumber(a, b) {
5761    return a = +a, b = +b, function(t) {
5762      return a * (1 - t) + b * t;
5763    };
5764  }
5765
5766  function object(a, b) {
5767    var i = {},
5768        c = {},
5769        k;
5770
5771    if (a === null || typeof a !== "object") a = {};
5772    if (b === null || typeof b !== "object") b = {};
5773
5774    for (k in b) {
5775      if (k in a) {
5776        i[k] = interpolate(a[k], b[k]);
5777      } else {
5778        c[k] = b[k];
5779      }
5780    }
5781
5782    return function(t) {
5783      for (k in i) c[k] = i[k](t);
5784      return c;
5785    };
5786  }
5787
5788  var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
5789      reB = new RegExp(reA.source, "g");
5790
5791  function zero(b) {
5792    return function() {
5793      return b;
5794    };
5795  }
5796
5797  function one(b) {
5798    return function(t) {
5799      return b(t) + "";
5800    };
5801  }
5802
5803  function string(a, b) {
5804    var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
5805        am, // current match in a
5806        bm, // current match in b
5807        bs, // string preceding current number in b, if any
5808        i = -1, // index in s
5809        s = [], // string constants and placeholders
5810        q = []; // number interpolators
5811
5812    // Coerce inputs to strings.
5813    a = a + "", b = b + "";
5814
5815    // Interpolate pairs of numbers in a & b.
5816    while ((am = reA.exec(a))
5817        && (bm = reB.exec(b))) {
5818      if ((bs = bm.index) > bi) { // a string precedes the next number in b
5819        bs = b.slice(bi, bs);
5820        if (s[i]) s[i] += bs; // coalesce with previous string
5821        else s[++i] = bs;
5822      }
5823      if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
5824        if (s[i]) s[i] += bm; // coalesce with previous string
5825        else s[++i] = bm;
5826      } else { // interpolate non-matching numbers
5827        s[++i] = null;
5828        q.push({i: i, x: interpolateNumber(am, bm)});
5829      }
5830      bi = reB.lastIndex;
5831    }
5832
5833    // Add remains of b.
5834    if (bi < b.length) {
5835      bs = b.slice(bi);
5836      if (s[i]) s[i] += bs; // coalesce with previous string
5837      else s[++i] = bs;
5838    }
5839
5840    // Special optimization for only a single match.
5841    // Otherwise, interpolate each of the numbers and rejoin the string.
5842    return s.length < 2 ? (q[0]
5843        ? one(q[0].x)
5844        : zero(b))
5845        : (b = q.length, function(t) {
5846            for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
5847            return s.join("");
5848          });
5849  }
5850
5851  function interpolate(a, b) {
5852    var t = typeof b, c;
5853    return b == null || t === "boolean" ? constant(b)
5854        : (t === "number" ? interpolateNumber
5855        : t === "string" ? ((c = color(b)) ? (b = c, rgb$1) : string)
5856        : b instanceof color ? rgb$1
5857        : b instanceof Date ? date
5858        : isNumberArray(b) ? numberArray
5859        : Array.isArray(b) ? genericArray
5860        : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object
5861        : interpolateNumber)(a, b);
5862  }
5863
5864  function interpolateRound(a, b) {
5865    return a = +a, b = +b, function(t) {
5866      return Math.round(a * (1 - t) + b * t);
5867    };
5868  }
5869
5870  function constant$1(x) {
5871    return function() {
5872      return x;
5873    };
5874  }
5875
5876  function number(x) {
5877    return +x;
5878  }
5879
5880  var unit = [0, 1];
5881
5882  function identity(x) {
5883    return x;
5884  }
5885
5886  function normalize(a, b) {
5887    return (b -= (a = +a))
5888        ? function(x) { return (x - a) / b; }
5889        : constant$1(isNaN(b) ? NaN : 0.5);
5890  }
5891
5892  function clamper(a, b) {
5893    var t;
5894    if (a > b) t = a, a = b, b = t;
5895    return function(x) { return Math.max(a, Math.min(b, x)); };
5896  }
5897
5898  // normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
5899  // interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b].
5900  function bimap(domain, range, interpolate) {
5901    var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1];
5902    if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0);
5903    else d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
5904    return function(x) { return r0(d0(x)); };
5905  }
5906
5907  function polymap(domain, range, interpolate) {
5908    var j = Math.min(domain.length, range.length) - 1,
5909        d = new Array(j),
5910        r = new Array(j),
5911        i = -1;
5912
5913    // Reverse descending domains.
5914    if (domain[j] < domain[0]) {
5915      domain = domain.slice().reverse();
5916      range = range.slice().reverse();
5917    }
5918
5919    while (++i < j) {
5920      d[i] = normalize(domain[i], domain[i + 1]);
5921      r[i] = interpolate(range[i], range[i + 1]);
5922    }
5923
5924    return function(x) {
5925      var i = bisectRight(domain, x, 1, j) - 1;
5926      return r[i](d[i](x));
5927    };
5928  }
5929
5930  function copy(source, target) {
5931    return target
5932        .domain(source.domain())
5933        .range(source.range())
5934        .interpolate(source.interpolate())
5935        .clamp(source.clamp())
5936        .unknown(source.unknown());
5937  }
5938
5939  function transformer() {
5940    var domain = unit,
5941        range = unit,
5942        interpolate$1 = interpolate,
5943        transform,
5944        untransform,
5945        unknown,
5946        clamp = identity,
5947        piecewise,
5948        output,
5949        input;
5950
5951    function rescale() {
5952      var n = Math.min(domain.length, range.length);
5953      if (clamp !== identity) clamp = clamper(domain[0], domain[n - 1]);
5954      piecewise = n > 2 ? polymap : bimap;
5955      output = input = null;
5956      return scale;
5957    }
5958
5959    function scale(x) {
5960      return isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate$1)))(transform(clamp(x)));
5961    }
5962
5963    scale.invert = function(y) {
5964      return clamp(untransform((input || (input = piecewise(range, domain.map(transform), interpolateNumber)))(y)));
5965    };
5966
5967    scale.domain = function(_) {
5968      return arguments.length ? (domain = Array.from(_, number), rescale()) : domain.slice();
5969    };
5970
5971    scale.range = function(_) {
5972      return arguments.length ? (range = Array.from(_), rescale()) : range.slice();
5973    };
5974
5975    scale.rangeRound = function(_) {
5976      return range = Array.from(_), interpolate$1 = interpolateRound, rescale();
5977    };
5978
5979    scale.clamp = function(_) {
5980      return arguments.length ? (clamp = _ ? true : identity, rescale()) : clamp !== identity;
5981    };
5982
5983    scale.interpolate = function(_) {
5984      return arguments.length ? (interpolate$1 = _, rescale()) : interpolate$1;
5985    };
5986
5987    scale.unknown = function(_) {
5988      return arguments.length ? (unknown = _, scale) : unknown;
5989    };
5990
5991    return function(t, u) {
5992      transform = t, untransform = u;
5993      return rescale();
5994    };
5995  }
5996
5997  function continuous() {
5998    return transformer()(identity, identity);
5999  }
6000
6001  // Computes the decimal coefficient and exponent of the specified number x with
6002  // significant digits p, where x is positive and p is in [1, 21] or undefined.
6003  // For example, formatDecimal(1.23) returns ["123", 0].
6004  function formatDecimal(x, p) {
6005    if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
6006    var i, coefficient = x.slice(0, i);
6007
6008    // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
6009    // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
6010    return [
6011      coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
6012      +x.slice(i + 1)
6013    ];
6014  }
6015
6016  function exponent(x) {
6017    return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
6018  }
6019
6020  function formatGroup(grouping, thousands) {
6021    return function(value, width) {
6022      var i = value.length,
6023          t = [],
6024          j = 0,
6025          g = grouping[0],
6026          length = 0;
6027
6028      while (i > 0 && g > 0) {
6029        if (length + g + 1 > width) g = Math.max(1, width - length);
6030        t.push(value.substring(i -= g, i + g));
6031        if ((length += g + 1) > width) break;
6032        g = grouping[j = (j + 1) % grouping.length];
6033      }
6034
6035      return t.reverse().join(thousands);
6036    };
6037  }
6038
6039  function formatNumerals(numerals) {
6040    return function(value) {
6041      return value.replace(/[0-9]/g, function(i) {
6042        return numerals[+i];
6043      });
6044    };
6045  }
6046
6047  // [[fill]align][sign][symbol][0][width][,][.precision][~][type]
6048  var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
6049
6050  function formatSpecifier(specifier) {
6051    if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
6052    var match;
6053    return new FormatSpecifier({
6054      fill: match[1],
6055      align: match[2],
6056      sign: match[3],
6057      symbol: match[4],
6058      zero: match[5],
6059      width: match[6],
6060      comma: match[7],
6061      precision: match[8] && match[8].slice(1),
6062      trim: match[9],
6063      type: match[10]
6064    });
6065  }
6066
6067  formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
6068
6069  function FormatSpecifier(specifier) {
6070    this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
6071    this.align = specifier.align === undefined ? ">" : specifier.align + "";
6072    this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
6073    this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
6074    this.zero = !!specifier.zero;
6075    this.width = specifier.width === undefined ? undefined : +specifier.width;
6076    this.comma = !!specifier.comma;
6077    this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
6078    this.trim = !!specifier.trim;
6079    this.type = specifier.type === undefined ? "" : specifier.type + "";
6080  }
6081
6082  FormatSpecifier.prototype.toString = function() {
6083    return this.fill
6084        + this.align
6085        + this.sign
6086        + this.symbol
6087        + (this.zero ? "0" : "")
6088        + (this.width === undefined ? "" : Math.max(1, this.width | 0))
6089        + (this.comma ? "," : "")
6090        + (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0))
6091        + (this.trim ? "~" : "")
6092        + this.type;
6093  };
6094
6095  // Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
6096  function formatTrim(s) {
6097    out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
6098      switch (s[i]) {
6099        case ".": i0 = i1 = i; break;
6100        case "0": if (i0 === 0) i0 = i; i1 = i; break;
6101        default: if (!+s[i]) break out; if (i0 > 0) i0 = 0; break;
6102      }
6103    }
6104    return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
6105  }
6106
6107  var prefixExponent;
6108
6109  function formatPrefixAuto(x, p) {
6110    var d = formatDecimal(x, p);
6111    if (!d) return x + "";
6112    var coefficient = d[0],
6113        exponent = d[1],
vendor: 10,369 bytes, lines 6114-6385
6114        i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
6115        n = coefficient.length;
6116    return i === n ? coefficient
6117        : i > n ? coefficient + new Array(i - n + 1).join("0")
6118        : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
6119        : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
6120  }
6121
6122  function formatRounded(x, p) {
6123    var d = formatDecimal(x, p);
6124    if (!d) return x + "";
6125    var coefficient = d[0],
6126        exponent = d[1];
6127    return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
6128        : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
6129        : coefficient + new Array(exponent - coefficient.length + 2).join("0");
6130  }
6131
6132  var formatTypes = {
6133    "%": function(x, p) { return (x * 100).toFixed(p); },
6134    "b": function(x) { return Math.round(x).toString(2); },
6135    "c": function(x) { return x + ""; },
6136    "d": function(x) { return Math.round(x).toString(10); },
6137    "e": function(x, p) { return x.toExponential(p); },
6138    "f": function(x, p) { return x.toFixed(p); },
6139    "g": function(x, p) { return x.toPrecision(p); },
6140    "o": function(x) { return Math.round(x).toString(8); },
6141    "p": function(x, p) { return formatRounded(x * 100, p); },
6142    "r": formatRounded,
6143    "s": formatPrefixAuto,
6144    "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
6145    "x": function(x) { return Math.round(x).toString(16); }
6146  };
6147
6148  function identity$1(x) {
6149    return x;
6150  }
6151
6152  var map = Array.prototype.map,
6153      prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
6154
6155  function formatLocale(locale) {
6156    var group = locale.grouping === undefined || locale.thousands === undefined ? identity$1 : formatGroup(map.call(locale.grouping, Number), locale.thousands + ""),
6157        currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
6158        currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
6159        decimal = locale.decimal === undefined ? "." : locale.decimal + "",
6160        numerals = locale.numerals === undefined ? identity$1 : formatNumerals(map.call(locale.numerals, String)),
6161        percent = locale.percent === undefined ? "%" : locale.percent + "",
6162        minus = locale.minus === undefined ? "-" : locale.minus + "",
6163        nan = locale.nan === undefined ? "NaN" : locale.nan + "";
6164
6165    function newFormat(specifier) {
6166      specifier = formatSpecifier(specifier);
6167
6168      var fill = specifier.fill,
6169          align = specifier.align,
6170          sign = specifier.sign,
6171          symbol = specifier.symbol,
6172          zero = specifier.zero,
6173          width = specifier.width,
6174          comma = specifier.comma,
6175          precision = specifier.precision,
6176          trim = specifier.trim,
6177          type = specifier.type;
6178
6179      // The "n" type is an alias for ",g".
6180      if (type === "n") comma = true, type = "g";
6181
6182      // The "" type, and any invalid type, is an alias for ".12~g".
6183      else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g";
6184
6185      // If zero fill is specified, padding goes after sign and before digits.
6186      if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
6187
6188      // Compute the prefix and suffix.
6189      // For SI-prefix, the suffix is lazily computed.
6190      var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
6191          suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : "";
6192
6193      // What format function should we use?
6194      // Is this an integer type?
6195      // Can this type generate exponential notation?
6196      var formatType = formatTypes[type],
6197          maybeSuffix = /[defgprs%]/.test(type);
6198
6199      // Set the default precision if not specified,
6200      // or clamp the specified precision to the supported range.
6201      // For significant precision, it must be in [1, 21].
6202      // For fixed precision, it must be in [0, 20].
6203      precision = precision === undefined ? 6
6204          : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
6205          : Math.max(0, Math.min(20, precision));
6206
6207      function format(value) {
6208        var valuePrefix = prefix,
6209            valueSuffix = suffix,
6210            i, n, c;
6211
6212        if (type === "c") {
6213          valueSuffix = formatType(value) + valueSuffix;
6214          value = "";
6215        } else {
6216          value = +value;
6217
6218          // Determine the sign. -0 is not less than 0, but 1 / -0 is!
6219          var valueNegative = value < 0 || 1 / value < 0;
6220
6221          // Perform the initial formatting.
6222          value = isNaN(value) ? nan : formatType(Math.abs(value), precision);
6223
6224          // Trim insignificant zeros.
6225          if (trim) value = formatTrim(value);
6226
6227          // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
6228          if (valueNegative && +value === 0 && sign !== "+") valueNegative = false;
6229
6230          // Compute the prefix and suffix.
6231          valuePrefix = (valueNegative ? (sign === "(" ? sign : minus) : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
6232          valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : "");
6233
6234          // Break the formatted value into the integer “value” part that can be
6235          // grouped, and fractional or exponential “suffix” part that is not.
6236          if (maybeSuffix) {
6237            i = -1, n = value.length;
6238            while (++i < n) {
6239              if (c = value.charCodeAt(i), 48 > c || c > 57) {
6240                valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
6241                value = value.slice(0, i);
6242                break;
6243              }
6244            }
6245          }
6246        }
6247
6248        // If the fill character is not "0", grouping is applied before padding.
6249        if (comma && !zero) value = group(value, Infinity);
6250
6251        // Compute the padding.
6252        var length = valuePrefix.length + value.length + valueSuffix.length,
6253            padding = length < width ? new Array(width - length + 1).join(fill) : "";
6254
6255        // If the fill character is "0", grouping is applied after padding.
6256        if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
6257
6258        // Reconstruct the final output based on the desired alignment.
6259        switch (align) {
6260          case "<": value = valuePrefix + value + valueSuffix + padding; break;
6261          case "=": value = valuePrefix + padding + value + valueSuffix; break;
6262          case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break;
6263          default: value = padding + valuePrefix + value + valueSuffix; break;
6264        }
6265
6266        return numerals(value);
6267      }
6268
6269      format.toString = function() {
6270        return specifier + "";
6271      };
6272
6273      return format;
6274    }
6275
6276    function formatPrefix(specifier, value) {
6277      var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
6278          e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
6279          k = Math.pow(10, -e),
6280          prefix = prefixes[8 + e / 3];
6281      return function(value) {
6282        return f(k * value) + prefix;
6283      };
6284    }
6285
6286    return {
6287      format: newFormat,
6288      formatPrefix: formatPrefix
6289    };
6290  }
6291
6292  var locale;
6293  var format;
6294  var formatPrefix;
6295
6296  defaultLocale({
6297    decimal: ".",
6298    thousands: ",",
6299    grouping: [3],
6300    currency: ["$", ""],
6301    minus: "-"
6302  });
6303
6304  function defaultLocale(definition) {
6305    locale = formatLocale(definition);
6306    format = locale.format;
6307    formatPrefix = locale.formatPrefix;
6308    return locale;
6309  }
6310
6311  function precisionFixed(step) {
6312    return Math.max(0, -exponent(Math.abs(step)));
6313  }
6314
6315  function precisionPrefix(step, value) {
6316    return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
6317  }
6318
6319  function precisionRound(step, max) {
6320    step = Math.abs(step), max = Math.abs(max) - step;
6321    return Math.max(0, exponent(max) - exponent(step)) + 1;
6322  }
6323
6324  function tickFormat(start, stop, count, specifier) {
6325    var step = tickStep(start, stop, count),
6326        precision;
6327    specifier = formatSpecifier(specifier == null ? ",f" : specifier);
6328    switch (specifier.type) {
6329      case "s": {
6330        var value = Math.max(Math.abs(start), Math.abs(stop));
6331        if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
6332        return formatPrefix(specifier, value);
6333      }
6334      case "":
6335      case "e":
6336      case "g":
6337      case "p":
6338      case "r": {
6339        if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
6340        break;
6341      }
6342      case "f":
6343      case "%": {
6344        if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
6345        break;
6346      }
6347    }
6348    return format(specifier);
6349  }
6350
6351  function linearish(scale) {
6352    var domain = scale.domain;
6353
6354    scale.ticks = function(count) {
6355      var d = domain();
6356      return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
6357    };
6358
6359    scale.tickFormat = function(count, specifier) {
6360      var d = domain();
6361      return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
6362    };
6363
6364    scale.nice = function(count) {
6365      if (count == null) count = 10;
6366
6367      var d = domain(),
6368          i0 = 0,
6369          i1 = d.length - 1,
6370          start = d[i0],
6371          stop = d[i1],
6372          step;
6373
6374      if (stop < start) {
6375        step = start, start = stop, stop = step;
6376        step = i0, i0 = i1, i1 = step;
6377      }
6378
6379      step = tickIncrement(start, stop, count);
6380
6381      if (step > 0) {
6382        start = Math.floor(start / step) * step;
6383        stop = Math.ceil(stop / step) * step;
6384        step = tickIncrement(start, stop, count);
6385      } else if (step < 0) {
6386        start = Math.ceil(start * step) / step;
6387        stop = Math.floor(stop * step) / step;
6388        step = tickIncrement(start, stop, count);
6389      }
6390
6391      if (step > 0) {
6392        d[i0] = Math.floor(start / step) * step;
6393        d[i1] = Math.ceil(stop / step) * step;
6394        domain(d);
6395      } else if (step < 0) {
6396        d[i0] = Math.ceil(start * step) / step;
6397        d[i1] = Math.floor(stop * step) / step;
6398        domain(d);
6399      }
6400
6401      return scale;
6402    };
6403
6404    return scale;
6405  }
6406
6407  function linear$1() {
6408    var scale = continuous();
6409
6410    scale.copy = function() {
6411      return copy(scale, linear$1());
6412    };
6413
6414    initRange.apply(scale, arguments);
6415
6416    return linearish(scale);
6417  }
6418
6419  var t0$1 = new Date,
6420      t1$1 = new Date;
6421
6422  function newInterval(floori, offseti, count, field) {
6423
6424    function interval(date) {
6425      return floori(date = arguments.length === 0 ? new Date : new Date(+date)), date;
6426    }
6427
6428    interval.floor = function(date) {
6429      return floori(date = new Date(+date)), date;
6430    };
6431
6432    interval.ceil = function(date) {
6433      return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
6434    };
6435
6436    interval.round = function(date) {
6437      var d0 = interval(date),
6438          d1 = interval.ceil(date);
6439      return date - d0 < d1 - date ? d0 : d1;
6440    };
6441
6442    interval.offset = function(date, step) {
6443      return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
6444    };
6445
6446    interval.range = function(start, stop, step) {
6447      var range = [], previous;
6448      start = interval.ceil(start);
6449      step = step == null ? 1 : Math.floor(step);
6450      if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
6451      do range.push(previous = new Date(+start)), offseti(start, step), floori(start);
6452      while (previous < start && start < stop);
6453      return range;
6454    };
6455
6456    interval.filter = function(test) {
6457      return newInterval(function(date) {
6458        if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
6459      }, function(date, step) {
6460        if (date >= date) {
6461          if (step < 0) while (++step <= 0) {
6462            while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty
6463          } else while (--step >= 0) {
6464            while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty
6465          }
6466        }
6467      });
6468    };
6469
6470    if (count) {
6471      interval.count = function(start, end) {
6472        t0$1.setTime(+start), t1$1.setTime(+end);
6473        floori(t0$1), floori(t1$1);
6474        return Math.floor(count(t0$1, t1$1));
6475      };
6476
6477      interval.every = function(step) {
6478        step = Math.floor(step);
6479        return !isFinite(step) || !(step > 0) ? null
6480            : !(step > 1) ? interval
6481            : interval.filter(field
6482                ? function(d) { return field(d) % step === 0; }
6483                : function(d) { return interval.count(0, d) % step === 0; });
6484      };
6485    }
6486
6487    return interval;
6488  }
6489
6490  var millisecond = newInterval(function() {
6491    // noop
6492  }, function(date, step) {
6493    date.setTime(+date + step);
6494  }, function(start, end) {
6495    return end - start;
6496  });
6497
6498  // An optimized implementation for this simple case.
6499  millisecond.every = function(k) {
6500    k = Math.floor(k);
6501    if (!isFinite(k) || !(k > 0)) return null;
6502    if (!(k > 1)) return millisecond;
6503    return newInterval(function(date) {
6504      date.setTime(Math.floor(date / k) * k);
6505    }, function(date, step) {
6506      date.setTime(+date + step * k);
6507    }, function(start, end) {
6508      return (end - start) / k;
6509    });
6510  };
6511
6512  var durationSecond = 1e3;
6513  var durationMinute = 6e4;
6514  var durationHour = 36e5;
6515  var durationDay = 864e5;
6516  var durationWeek = 6048e5;
6517
6518  var second = newInterval(function(date) {
6519    date.setTime(date - date.getMilliseconds());
6520  }, function(date, step) {
6521    date.setTime(+date + step * durationSecond);
6522  }, function(start, end) {
6523    return (end - start) / durationSecond;
6524  }, function(date) {
6525    return date.getUTCSeconds();
6526  });
6527
6528  var minute = newInterval(function(date) {
6529    date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond);
6530  }, function(date, step) {
6531    date.setTime(+date + step * durationMinute);
6532  }, function(start, end) {
6533    return (end - start) / durationMinute;
6534  }, function(date) {
6535    return date.getMinutes();
6536  });
6537
6538  var hour = newInterval(function(date) {
6539    date.setTime(date - date.getMilliseconds() - date.getSeconds() * durationSecond - date.getMinutes() * durationMinute);
6540  }, function(date, step) {
6541    date.setTime(+date + step * durationHour);
6542  }, function(start, end) {
6543    return (end - start) / durationHour;
6544  }, function(date) {
6545    return date.getHours();
6546  });
6547
6548  var day = newInterval(function(date) {
6549    date.setHours(0, 0, 0, 0);
6550  }, function(date, step) {
6551    date.setDate(date.getDate() + step);
6552  }, function(start, end) {
6553    return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay;
6554  }, function(date) {
6555    return date.getDate() - 1;
6556  });
6557
6558  function weekday(i) {
6559    return newInterval(function(date) {
6560      date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
6561      date.setHours(0, 0, 0, 0);
6562    }, function(date, step) {
6563      date.setDate(date.getDate() + step * 7);
6564    }, function(start, end) {
6565      return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek;
6566    });
6567  }
6568
6569  var sunday = weekday(0);
6570  var monday = weekday(1);
6571  var tuesday = weekday(2);
6572  var wednesday = weekday(3);
6573  var thursday = weekday(4);
6574  var friday = weekday(5);
6575  var saturday = weekday(6);
6576
vendor: 5,511 bytes, lines 6577-6749
6577  var month = newInterval(function(date) {
6578    date.setDate(1);
6579    date.setHours(0, 0, 0, 0);
6580  }, function(date, step) {
6581    date.setMonth(date.getMonth() + step);
6582  }, function(start, end) {
6583    return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
6584  }, function(date) {
6585    return date.getMonth();
6586  });
6587
6588  var year = newInterval(function(date) {
6589    date.setMonth(0, 1);
6590    date.setHours(0, 0, 0, 0);
6591  }, function(date, step) {
6592    date.setFullYear(date.getFullYear() + step);
6593  }, function(start, end) {
6594    return end.getFullYear() - start.getFullYear();
6595  }, function(date) {
6596    return date.getFullYear();
6597  });
6598
6599  // An optimized implementation for this simple case.
6600  year.every = function(k) {
6601    return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
6602      date.setFullYear(Math.floor(date.getFullYear() / k) * k);
6603      date.setMonth(0, 1);
6604      date.setHours(0, 0, 0, 0);
6605    }, function(date, step) {
6606      date.setFullYear(date.getFullYear() + step * k);
6607    });
6608  };
6609
6610  var utcMinute = newInterval(function(date) {
6611    date.setUTCSeconds(0, 0);
6612  }, function(date, step) {
6613    date.setTime(+date + step * durationMinute);
6614  }, function(start, end) {
6615    return (end - start) / durationMinute;
6616  }, function(date) {
6617    return date.getUTCMinutes();
6618  });
6619
6620  var utcHour = newInterval(function(date) {
6621    date.setUTCMinutes(0, 0, 0);
6622  }, function(date, step) {
6623    date.setTime(+date + step * durationHour);
6624  }, function(start, end) {
6625    return (end - start) / durationHour;
6626  }, function(date) {
6627    return date.getUTCHours();
6628  });
6629
6630  var utcDay = newInterval(function(date) {
6631    date.setUTCHours(0, 0, 0, 0);
6632  }, function(date, step) {
6633    date.setUTCDate(date.getUTCDate() + step);
6634  }, function(start, end) {
6635    return (end - start) / durationDay;
6636  }, function(date) {
6637    return date.getUTCDate() - 1;
6638  });
6639
6640  function utcWeekday(i) {
6641    return newInterval(function(date) {
6642      date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
6643      date.setUTCHours(0, 0, 0, 0);
6644    }, function(date, step) {
6645      date.setUTCDate(date.getUTCDate() + step * 7);
6646    }, function(start, end) {
6647      return (end - start) / durationWeek;
6648    });
6649  }
6650
6651  var utcSunday = utcWeekday(0);
6652  var utcMonday = utcWeekday(1);
6653  var utcTuesday = utcWeekday(2);
6654  var utcWednesday = utcWeekday(3);
6655  var utcThursday = utcWeekday(4);
6656  var utcFriday = utcWeekday(5);
6657  var utcSaturday = utcWeekday(6);
6658
6659  var utcMonth = newInterval(function(date) {
6660    date.setUTCDate(1);
6661    date.setUTCHours(0, 0, 0, 0);
6662  }, function(date, step) {
6663    date.setUTCMonth(date.getUTCMonth() + step);
6664  }, function(start, end) {
6665    return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
6666  }, function(date) {
6667    return date.getUTCMonth();
6668  });
6669
6670  var utcYear = newInterval(function(date) {
6671    date.setUTCMonth(0, 1);
6672    date.setUTCHours(0, 0, 0, 0);
6673  }, function(date, step) {
6674    date.setUTCFullYear(date.getUTCFullYear() + step);
6675  }, function(start, end) {
6676    return end.getUTCFullYear() - start.getUTCFullYear();
6677  }, function(date) {
6678    return date.getUTCFullYear();
6679  });
6680
6681  // An optimized implementation for this simple case.
6682  utcYear.every = function(k) {
6683    return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
6684      date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
6685      date.setUTCMonth(0, 1);
6686      date.setUTCHours(0, 0, 0, 0);
6687    }, function(date, step) {
6688      date.setUTCFullYear(date.getUTCFullYear() + step * k);
6689    });
6690  };
6691
6692  function localDate(d) {
6693    if (0 <= d.y && d.y < 100) {
6694      var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
6695      date.setFullYear(d.y);
6696      return date;
6697    }
6698    return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
6699  }
6700
6701  function utcDate(d) {
6702    if (0 <= d.y && d.y < 100) {
6703      var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
6704      date.setUTCFullYear(d.y);
6705      return date;
6706    }
6707    return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
6708  }
6709
6710  function newDate(y, m, d) {
6711    return {y: y, m: m, d: d, H: 0, M: 0, S: 0, L: 0};
6712  }
6713
6714  function formatLocale$1(locale) {
6715    var locale_dateTime = locale.dateTime,
6716        locale_date = locale.date,
6717        locale_time = locale.time,
6718        locale_periods = locale.periods,
6719        locale_weekdays = locale.days,
6720        locale_shortWeekdays = locale.shortDays,
6721        locale_months = locale.months,
6722        locale_shortMonths = locale.shortMonths;
6723
6724    var periodRe = formatRe(locale_periods),
6725        periodLookup = formatLookup(locale_periods),
6726        weekdayRe = formatRe(locale_weekdays),
6727        weekdayLookup = formatLookup(locale_weekdays),
6728        shortWeekdayRe = formatRe(locale_shortWeekdays),
6729        shortWeekdayLookup = formatLookup(locale_shortWeekdays),
6730        monthRe = formatRe(locale_months),
6731        monthLookup = formatLookup(locale_months),
6732        shortMonthRe = formatRe(locale_shortMonths),
6733        shortMonthLookup = formatLookup(locale_shortMonths);
6734
6735    var formats = {
6736      "a": formatShortWeekday,
6737      "A": formatWeekday,
6738      "b": formatShortMonth,
6739      "B": formatMonth,
6740      "c": null,
6741      "d": formatDayOfMonth,
6742      "e": formatDayOfMonth,
6743      "f": formatMicroseconds,
6744      "H": formatHour24,
6745      "I": formatHour12,
6746      "j": formatDayOfYear,
6747      "L": formatMilliseconds,
6748      "m": formatMonthNumber,
6749      "M": formatMinutes,
vendor: 6,581 bytes, lines 6750-6955
6750      "p": formatPeriod,
6751      "q": formatQuarter,
6752      "Q": formatUnixTimestamp,
6753      "s": formatUnixTimestampSeconds,
6754      "S": formatSeconds,
6755      "u": formatWeekdayNumberMonday,
6756      "U": formatWeekNumberSunday,
6757      "V": formatWeekNumberISO,
6758      "w": formatWeekdayNumberSunday,
6759      "W": formatWeekNumberMonday,
6760      "x": null,
6761      "X": null,
6762      "y": formatYear,
6763      "Y": formatFullYear,
6764      "Z": formatZone,
6765      "%": formatLiteralPercent
6766    };
6767
6768    var utcFormats = {
6769      "a": formatUTCShortWeekday,
6770      "A": formatUTCWeekday,
6771      "b": formatUTCShortMonth,
6772      "B": formatUTCMonth,
6773      "c": null,
6774      "d": formatUTCDayOfMonth,
6775      "e": formatUTCDayOfMonth,
6776      "f": formatUTCMicroseconds,
6777      "H": formatUTCHour24,
6778      "I": formatUTCHour12,
6779      "j": formatUTCDayOfYear,
6780      "L": formatUTCMilliseconds,
6781      "m": formatUTCMonthNumber,
6782      "M": formatUTCMinutes,
6783      "p": formatUTCPeriod,
6784      "q": formatUTCQuarter,
6785      "Q": formatUnixTimestamp,
6786      "s": formatUnixTimestampSeconds,
6787      "S": formatUTCSeconds,
6788      "u": formatUTCWeekdayNumberMonday,
6789      "U": formatUTCWeekNumberSunday,
6790      "V": formatUTCWeekNumberISO,
6791      "w": formatUTCWeekdayNumberSunday,
6792      "W": formatUTCWeekNumberMonday,
6793      "x": null,
6794      "X": null,
6795      "y": formatUTCYear,
6796      "Y": formatUTCFullYear,
6797      "Z": formatUTCZone,
6798      "%": formatLiteralPercent
6799    };
6800
6801    var parses = {
6802      "a": parseShortWeekday,
6803      "A": parseWeekday,
6804      "b": parseShortMonth,
6805      "B": parseMonth,
6806      "c": parseLocaleDateTime,
6807      "d": parseDayOfMonth,
6808      "e": parseDayOfMonth,
6809      "f": parseMicroseconds,
6810      "H": parseHour24,
6811      "I": parseHour24,
6812      "j": parseDayOfYear,
6813      "L": parseMilliseconds,
6814      "m": parseMonthNumber,
6815      "M": parseMinutes,
6816      "p": parsePeriod,
6817      "q": parseQuarter,
6818      "Q": parseUnixTimestamp,
6819      "s": parseUnixTimestampSeconds,
6820      "S": parseSeconds,
6821      "u": parseWeekdayNumberMonday,
6822      "U": parseWeekNumberSunday,
6823      "V": parseWeekNumberISO,
6824      "w": parseWeekdayNumberSunday,
6825      "W": parseWeekNumberMonday,
6826      "x": parseLocaleDate,
6827      "X": parseLocaleTime,
6828      "y": parseYear,
6829      "Y": parseFullYear,
6830      "Z": parseZone,
6831      "%": parseLiteralPercent
6832    };
6833
6834    // These recursive directive definitions must be deferred.
6835    formats.x = newFormat(locale_date, formats);
6836    formats.X = newFormat(locale_time, formats);
6837    formats.c = newFormat(locale_dateTime, formats);
6838    utcFormats.x = newFormat(locale_date, utcFormats);
6839    utcFormats.X = newFormat(locale_time, utcFormats);
6840    utcFormats.c = newFormat(locale_dateTime, utcFormats);
6841
6842    function newFormat(specifier, formats) {
6843      return function(date) {
6844        var string = [],
6845            i = -1,
6846            j = 0,
6847            n = specifier.length,
6848            c,
6849            pad,
6850            format;
6851
6852        if (!(date instanceof Date)) date = new Date(+date);
6853
6854        while (++i < n) {
6855          if (specifier.charCodeAt(i) === 37) {
6856            string.push(specifier.slice(j, i));
6857            if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
6858            else pad = c === "e" ? " " : "0";
6859            if (format = formats[c]) c = format(date, pad);
6860            string.push(c);
6861            j = i + 1;
6862          }
6863        }
6864
6865        string.push(specifier.slice(j, i));
6866        return string.join("");
6867      };
6868    }
6869
6870    function newParse(specifier, Z) {
6871      return function(string) {
6872        var d = newDate(1900, undefined, 1),
6873            i = parseSpecifier(d, specifier, string += "", 0),
6874            week, day$1;
6875        if (i != string.length) return null;
6876
6877        // If a UNIX timestamp is specified, return it.
6878        if ("Q" in d) return new Date(d.Q);
6879        if ("s" in d) return new Date(d.s * 1000 + ("L" in d ? d.L : 0));
6880
6881        // If this is utcParse, never use the local timezone.
6882        if (Z && !("Z" in d)) d.Z = 0;
6883
6884        // The am-pm flag is 0 for AM, and 1 for PM.
6885        if ("p" in d) d.H = d.H % 12 + d.p * 12;
6886
6887        // If the month was not specified, inherit from the quarter.
6888        if (d.m === undefined) d.m = "q" in d ? d.q : 0;
6889
6890        // Convert day-of-week and week-of-year to day-of-year.
6891        if ("V" in d) {
6892          if (d.V < 1 || d.V > 53) return null;
6893          if (!("w" in d)) d.w = 1;
6894          if ("Z" in d) {
6895            week = utcDate(newDate(d.y, 0, 1)), day$1 = week.getUTCDay();
6896            week = day$1 > 4 || day$1 === 0 ? utcMonday.ceil(week) : utcMonday(week);
6897            week = utcDay.offset(week, (d.V - 1) * 7);
6898            d.y = week.getUTCFullYear();
6899            d.m = week.getUTCMonth();
6900            d.d = week.getUTCDate() + (d.w + 6) % 7;
6901          } else {
6902            week = localDate(newDate(d.y, 0, 1)), day$1 = week.getDay();
6903            week = day$1 > 4 || day$1 === 0 ? monday.ceil(week) : monday(week);
6904            week = day.offset(week, (d.V - 1) * 7);
6905            d.y = week.getFullYear();
6906            d.m = week.getMonth();
6907            d.d = week.getDate() + (d.w + 6) % 7;
6908          }
6909        } else if ("W" in d || "U" in d) {
6910          if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0;
6911          day$1 = "Z" in d ? utcDate(newDate(d.y, 0, 1)).getUTCDay() : localDate(newDate(d.y, 0, 1)).getDay();
6912          d.m = 0;
6913          d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$1 + 5) % 7 : d.w + d.U * 7 - (day$1 + 6) % 7;
6914        }
6915
6916        // If a time zone is specified, all fields are interpreted as UTC and then
6917        // offset according to the specified time zone.
6918        if ("Z" in d) {
6919          d.H += d.Z / 100 | 0;
6920          d.M += d.Z % 100;
6921          return utcDate(d);
6922        }
6923
6924        // Otherwise, all fields are in local time.
6925        return localDate(d);
6926      };
6927    }
6928
6929    function parseSpecifier(d, specifier, string, j) {
6930      var i = 0,
6931          n = specifier.length,
6932          m = string.length,
6933          c,
6934          parse;
6935
6936      while (i < n) {
6937        if (j >= m) return -1;
6938        c = specifier.charCodeAt(i++);
6939        if (c === 37) {
6940          c = specifier.charAt(i++);
6941          parse = parses[c in pads ? specifier.charAt(i++) : c];
6942          if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
6943        } else if (c != string.charCodeAt(j++)) {
6944          return -1;
6945        }
6946      }
6947
6948      return j;
6949    }
6950
6951    function parsePeriod(d, string, i) {
6952      var n = periodRe.exec(string.slice(i));
6953      return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
6954    }
6955
vendor: 3,735 bytes, lines 6956-7090
6956    function parseShortWeekday(d, string, i) {
6957      var n = shortWeekdayRe.exec(string.slice(i));
6958      return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
6959    }
6960
6961    function parseWeekday(d, string, i) {
6962      var n = weekdayRe.exec(string.slice(i));
6963      return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
6964    }
6965
6966    function parseShortMonth(d, string, i) {
6967      var n = shortMonthRe.exec(string.slice(i));
6968      return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
6969    }
6970
6971    function parseMonth(d, string, i) {
6972      var n = monthRe.exec(string.slice(i));
6973      return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
6974    }
6975
6976    function parseLocaleDateTime(d, string, i) {
6977      return parseSpecifier(d, locale_dateTime, string, i);
6978    }
6979
6980    function parseLocaleDate(d, string, i) {
6981      return parseSpecifier(d, locale_date, string, i);
6982    }
6983
6984    function parseLocaleTime(d, string, i) {
6985      return parseSpecifier(d, locale_time, string, i);
6986    }
6987
6988    function formatShortWeekday(d) {
6989      return locale_shortWeekdays[d.getDay()];
6990    }
6991
6992    function formatWeekday(d) {
6993      return locale_weekdays[d.getDay()];
6994    }
6995
6996    function formatShortMonth(d) {
6997      return locale_shortMonths[d.getMonth()];
6998    }
6999
7000    function formatMonth(d) {
7001      return locale_months[d.getMonth()];
7002    }
7003
7004    function formatPeriod(d) {
7005      return locale_periods[+(d.getHours() >= 12)];
7006    }
7007
7008    function formatQuarter(d) {
7009      return 1 + ~~(d.getMonth() / 3);
7010    }
7011
7012    function formatUTCShortWeekday(d) {
7013      return locale_shortWeekdays[d.getUTCDay()];
7014    }
7015
7016    function formatUTCWeekday(d) {
7017      return locale_weekdays[d.getUTCDay()];
7018    }
7019
7020    function formatUTCShortMonth(d) {
7021      return locale_shortMonths[d.getUTCMonth()];
7022    }
7023
7024    function formatUTCMonth(d) {
7025      return locale_months[d.getUTCMonth()];
7026    }
7027
7028    function formatUTCPeriod(d) {
7029      return locale_periods[+(d.getUTCHours() >= 12)];
7030    }
7031
7032    function formatUTCQuarter(d) {
7033      return 1 + ~~(d.getUTCMonth() / 3);
7034    }
7035
7036    return {
7037      format: function(specifier) {
7038        var f = newFormat(specifier += "", formats);
7039        f.toString = function() { return specifier; };
7040        return f;
7041      },
7042      parse: function(specifier) {
7043        var p = newParse(specifier += "", false);
7044        p.toString = function() { return specifier; };
7045        return p;
7046      },
7047      utcFormat: function(specifier) {
7048        var f = newFormat(specifier += "", utcFormats);
7049        f.toString = function() { return specifier; };
7050        return f;
7051      },
7052      utcParse: function(specifier) {
7053        var p = newParse(specifier += "", true);
7054        p.toString = function() { return specifier; };
7055        return p;
7056      }
7057    };
7058  }
7059
7060  var pads = {"-": "", "_": " ", "0": "0"},
7061      numberRe = /^\s*\d+/, // note: ignores next directive
7062      percentRe = /^%/,
7063      requoteRe = /[\\^$*+?|[\]().{}]/g;
7064
7065  function pad(value, fill, width) {
7066    var sign = value < 0 ? "-" : "",
7067        string = (sign ? -value : value) + "",
7068        length = string.length;
7069    return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
7070  }
7071
7072  function requote(s) {
7073    return s.replace(requoteRe, "\\$&");
7074  }
7075
7076  function formatRe(names) {
7077    return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
7078  }
7079
7080  function formatLookup(names) {
7081    var map = {}, i = -1, n = names.length;
7082    while (++i < n) map[names[i].toLowerCase()] = i;
7083    return map;
7084  }
7085
7086  function parseWeekdayNumberSunday(d, string, i) {
7087    var n = numberRe.exec(string.slice(i, i + 1));
7088    return n ? (d.w = +n[0], i + n[0].length) : -1;
7089  }
7090
vendor: 4,293 bytes, lines 7091-7244
7091  function parseWeekdayNumberMonday(d, string, i) {
7092    var n = numberRe.exec(string.slice(i, i + 1));
7093    return n ? (d.u = +n[0], i + n[0].length) : -1;
7094  }
7095
7096  function parseWeekNumberSunday(d, string, i) {
7097    var n = numberRe.exec(string.slice(i, i + 2));
7098    return n ? (d.U = +n[0], i + n[0].length) : -1;
7099  }
7100
7101  function parseWeekNumberISO(d, string, i) {
7102    var n = numberRe.exec(string.slice(i, i + 2));
7103    return n ? (d.V = +n[0], i + n[0].length) : -1;
7104  }
7105
7106  function parseWeekNumberMonday(d, string, i) {
7107    var n = numberRe.exec(string.slice(i, i + 2));
7108    return n ? (d.W = +n[0], i + n[0].length) : -1;
7109  }
7110
7111  function parseFullYear(d, string, i) {
7112    var n = numberRe.exec(string.slice(i, i + 4));
7113    return n ? (d.y = +n[0], i + n[0].length) : -1;
7114  }
7115
7116  function parseYear(d, string, i) {
7117    var n = numberRe.exec(string.slice(i, i + 2));
7118    return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
7119  }
7120
7121  function parseZone(d, string, i) {
7122    var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6));
7123    return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
7124  }
7125
7126  function parseQuarter(d, string, i) {
7127    var n = numberRe.exec(string.slice(i, i + 1));
7128    return n ? (d.q = n[0] * 3 - 3, i + n[0].length) : -1;
7129  }
7130
7131  function parseMonthNumber(d, string, i) {
7132    var n = numberRe.exec(string.slice(i, i + 2));
7133    return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
7134  }
7135
7136  function parseDayOfMonth(d, string, i) {
7137    var n = numberRe.exec(string.slice(i, i + 2));
7138    return n ? (d.d = +n[0], i + n[0].length) : -1;
7139  }
7140
7141  function parseDayOfYear(d, string, i) {
7142    var n = numberRe.exec(string.slice(i, i + 3));
7143    return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
7144  }
7145
7146  function parseHour24(d, string, i) {
7147    var n = numberRe.exec(string.slice(i, i + 2));
7148    return n ? (d.H = +n[0], i + n[0].length) : -1;
7149  }
7150
7151  function parseMinutes(d, string, i) {
7152    var n = numberRe.exec(string.slice(i, i + 2));
7153    return n ? (d.M = +n[0], i + n[0].length) : -1;
7154  }
7155
7156  function parseSeconds(d, string, i) {
7157    var n = numberRe.exec(string.slice(i, i + 2));
7158    return n ? (d.S = +n[0], i + n[0].length) : -1;
7159  }
7160
7161  function parseMilliseconds(d, string, i) {
7162    var n = numberRe.exec(string.slice(i, i + 3));
7163    return n ? (d.L = +n[0], i + n[0].length) : -1;
7164  }
7165
7166  function parseMicroseconds(d, string, i) {
7167    var n = numberRe.exec(string.slice(i, i + 6));
7168    return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1;
7169  }
7170
7171  function parseLiteralPercent(d, string, i) {
7172    var n = percentRe.exec(string.slice(i, i + 1));
7173    return n ? i + n[0].length : -1;
7174  }
7175
7176  function parseUnixTimestamp(d, string, i) {
7177    var n = numberRe.exec(string.slice(i));
7178    return n ? (d.Q = +n[0], i + n[0].length) : -1;
7179  }
7180
7181  function parseUnixTimestampSeconds(d, string, i) {
7182    var n = numberRe.exec(string.slice(i));
7183    return n ? (d.s = +n[0], i + n[0].length) : -1;
7184  }
7185
7186  function formatDayOfMonth(d, p) {
7187    return pad(d.getDate(), p, 2);
7188  }
7189
7190  function formatHour24(d, p) {
7191    return pad(d.getHours(), p, 2);
7192  }
7193
7194  function formatHour12(d, p) {
7195    return pad(d.getHours() % 12 || 12, p, 2);
7196  }
7197
7198  function formatDayOfYear(d, p) {
7199    return pad(1 + day.count(year(d), d), p, 3);
7200  }
7201
7202  function formatMilliseconds(d, p) {
7203    return pad(d.getMilliseconds(), p, 3);
7204  }
7205
7206  function formatMicroseconds(d, p) {
7207    return formatMilliseconds(d, p) + "000";
7208  }
7209
7210  function formatMonthNumber(d, p) {
7211    return pad(d.getMonth() + 1, p, 2);
7212  }
7213
7214  function formatMinutes(d, p) {
7215    return pad(d.getMinutes(), p, 2);
7216  }
7217
7218  function formatSeconds(d, p) {
7219    return pad(d.getSeconds(), p, 2);
7220  }
7221
7222  function formatWeekdayNumberMonday(d) {
7223    var day = d.getDay();
7224    return day === 0 ? 7 : day;
7225  }
7226
7227  function formatWeekNumberSunday(d, p) {
7228    return pad(sunday.count(year(d) - 1, d), p, 2);
7229  }
7230
7231  function formatWeekNumberISO(d, p) {
7232    var day = d.getDay();
7233    d = (day >= 4 || day === 0) ? thursday(d) : thursday.ceil(d);
7234    return pad(thursday.count(year(d), d) + (year(d).getDay() === 4), p, 2);
7235  }
7236
7237  function formatWeekdayNumberSunday(d) {
7238    return d.getDay();
7239  }
7240
7241  function formatWeekNumberMonday(d, p) {
7242    return pad(monday.count(year(d) - 1, d), p, 2);
7243  }
7244
vendor: 8,202 bytes, lines 7245-7525
7245  function formatYear(d, p) {
7246    return pad(d.getFullYear() % 100, p, 2);
7247  }
7248
7249  function formatFullYear(d, p) {
7250    return pad(d.getFullYear() % 10000, p, 4);
7251  }
7252
7253  function formatZone(d) {
7254    var z = d.getTimezoneOffset();
7255    return (z > 0 ? "-" : (z *= -1, "+"))
7256        + pad(z / 60 | 0, "0", 2)
7257        + pad(z % 60, "0", 2);
7258  }
7259
7260  function formatUTCDayOfMonth(d, p) {
7261    return pad(d.getUTCDate(), p, 2);
7262  }
7263
7264  function formatUTCHour24(d, p) {
7265    return pad(d.getUTCHours(), p, 2);
7266  }
7267
7268  function formatUTCHour12(d, p) {
7269    return pad(d.getUTCHours() % 12 || 12, p, 2);
7270  }
7271
7272  function formatUTCDayOfYear(d, p) {
7273    return pad(1 + utcDay.count(utcYear(d), d), p, 3);
7274  }
7275
7276  function formatUTCMilliseconds(d, p) {
7277    return pad(d.getUTCMilliseconds(), p, 3);
7278  }
7279
7280  function formatUTCMicroseconds(d, p) {
7281    return formatUTCMilliseconds(d, p) + "000";
7282  }
7283
7284  function formatUTCMonthNumber(d, p) {
7285    return pad(d.getUTCMonth() + 1, p, 2);
7286  }
7287
7288  function formatUTCMinutes(d, p) {
7289    return pad(d.getUTCMinutes(), p, 2);
7290  }
7291
7292  function formatUTCSeconds(d, p) {
7293    return pad(d.getUTCSeconds(), p, 2);
7294  }
7295
7296  function formatUTCWeekdayNumberMonday(d) {
7297    var dow = d.getUTCDay();
7298    return dow === 0 ? 7 : dow;
7299  }
7300
7301  function formatUTCWeekNumberSunday(d, p) {
7302    return pad(utcSunday.count(utcYear(d) - 1, d), p, 2);
7303  }
7304
7305  function formatUTCWeekNumberISO(d, p) {
7306    var day = d.getUTCDay();
7307    d = (day >= 4 || day === 0) ? utcThursday(d) : utcThursday.ceil(d);
7308    return pad(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2);
7309  }
7310
7311  function formatUTCWeekdayNumberSunday(d) {
7312    return d.getUTCDay();
7313  }
7314
7315  function formatUTCWeekNumberMonday(d, p) {
7316    return pad(utcMonday.count(utcYear(d) - 1, d), p, 2);
7317  }
7318
7319  function formatUTCYear(d, p) {
7320    return pad(d.getUTCFullYear() % 100, p, 2);
7321  }
7322
7323  function formatUTCFullYear(d, p) {
7324    return pad(d.getUTCFullYear() % 10000, p, 4);
7325  }
7326
7327  function formatUTCZone() {
7328    return "+0000";
7329  }
7330
7331  function formatLiteralPercent() {
7332    return "%";
7333  }
7334
7335  function formatUnixTimestamp(d) {
7336    return +d;
7337  }
7338
7339  function formatUnixTimestampSeconds(d) {
7340    return Math.floor(+d / 1000);
7341  }
7342
7343  var locale$1;
7344  var timeFormat;
7345  var timeParse;
7346  var utcFormat;
7347  var utcParse;
7348
7349  defaultLocale$1({
7350    dateTime: "%x, %X",
7351    date: "%-m/%-d/%Y",
7352    time: "%-I:%M:%S %p",
7353    periods: ["AM", "PM"],
7354    days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
7355    shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
7356    months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
7357    shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
7358  });
7359
7360  function defaultLocale$1(definition) {
7361    locale$1 = formatLocale$1(definition);
7362    timeFormat = locale$1.format;
7363    timeParse = locale$1.parse;
7364    utcFormat = locale$1.utcFormat;
7365    utcParse = locale$1.utcParse;
7366    return locale$1;
7367  }
7368
7369  var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
7370
7371  function formatIsoNative(date) {
7372    return date.toISOString();
7373  }
7374
7375  var formatIso = Date.prototype.toISOString
7376      ? formatIsoNative
7377      : utcFormat(isoSpecifier);
7378
7379  function parseIsoNative(string) {
7380    var date = new Date(string);
7381    return isNaN(date) ? null : date;
7382  }
7383
7384  var parseIso = +new Date("2000-01-01T00:00:00.000Z")
7385      ? parseIsoNative
7386      : utcParse(isoSpecifier);
7387
7388  var noop = {value: function() {}};
7389
7390  function dispatch() {
7391    for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
7392      if (!(t = arguments[i] + "") || (t in _) || /[\s.]/.test(t)) throw new Error("illegal type: " + t);
7393      _[t] = [];
7394    }
7395    return new Dispatch(_);
7396  }
7397
7398  function Dispatch(_) {
7399    this._ = _;
7400  }
7401
7402  function parseTypenames(typenames, types) {
7403    return typenames.trim().split(/^|\s+/).map(function(t) {
7404      var name = "", i = t.indexOf(".");
7405      if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
7406      if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
7407      return {type: t, name: name};
7408    });
7409  }
7410
7411  Dispatch.prototype = dispatch.prototype = {
7412    constructor: Dispatch,
7413    on: function(typename, callback) {
7414      var _ = this._,
7415          T = parseTypenames(typename + "", _),
7416          t,
7417          i = -1,
7418          n = T.length;
7419
7420      // If no callback was specified, return the callback of the given type and name.
7421      if (arguments.length < 2) {
7422        while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
7423        return;
7424      }
7425
7426      // If a type was specified, set the callback for the given type and name.
7427      // Otherwise, if a null callback was specified, remove callbacks of the given name.
7428      if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
7429      while (++i < n) {
7430        if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);
7431        else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);
7432      }
7433
7434      return this;
7435    },
7436    copy: function() {
7437      var copy = {}, _ = this._;
7438      for (var t in _) copy[t] = _[t].slice();
7439      return new Dispatch(copy);
7440    },
7441    call: function(type, that) {
7442      if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
7443      if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
7444      for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
7445    },
7446    apply: function(type, that, args) {
7447      if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
7448      for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
7449    }
7450  };
7451
7452  function get(type, name) {
7453    for (var i = 0, n = type.length, c; i < n; ++i) {
7454      if ((c = type[i]).name === name) {
7455        return c.value;
7456      }
7457    }
7458  }
7459
7460  function set(type, name, callback) {
7461    for (var i = 0, n = type.length; i < n; ++i) {
7462      if (type[i].name === name) {
7463        type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
7464        break;
7465      }
7466    }
7467    if (callback != null) type.push({name: name, value: callback});
7468    return type;
7469  }
7470
7471  var xhtml = "http://www.w3.org/1999/xhtml";
7472
7473  var namespaces = {
7474    svg: "http://www.w3.org/2000/svg",
7475    xhtml: xhtml,
7476    xlink: "http://www.w3.org/1999/xlink",
7477    xml: "http://www.w3.org/XML/1998/namespace",
7478    xmlns: "http://www.w3.org/2000/xmlns/"
7479  };
7480
7481  function namespace(name) {
7482    var prefix = name += "", i = prefix.indexOf(":");
7483    if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
7484    return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
7485  }
7486
7487  function creatorInherit(name) {
7488    return function() {
7489      var document = this.ownerDocument,
7490          uri = this.namespaceURI;
7491      return uri === xhtml && document.documentElement.namespaceURI === xhtml
7492          ? document.createElement(name)
7493          : document.createElementNS(uri, name);
7494    };
7495  }
7496
7497  function creatorFixed(fullname) {
7498    return function() {
7499      return this.ownerDocument.createElementNS(fullname.space, fullname.local);
7500    };
7501  }
7502
7503  function creator(name) {
7504    var fullname = namespace(name);
7505    return (fullname.local
7506        ? creatorFixed
7507        : creatorInherit)(fullname);
7508  }
7509
7510  function none() {}
7511
7512  function selector(selector) {
7513    return selector == null ? none : function() {
7514      return this.querySelector(selector);
7515    };
7516  }
7517
7518  function selection_select(select) {
7519    if (typeof select !== "function") select = selector(select);
7520
7521    for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
7522      for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
7523        if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
7524          if ("__data__" in node) subnode.__data__ = node.__data__;
7525          subgroup[i] = subnode;
7526        }
7527      }
7528    }
7529
7530    return new Selection(subgroups, this._parents);
7531  }
7532
7533  function empty() {
7534    return [];
7535  }
7536
7537  function selectorAll(selector) {
7538    return selector == null ? empty : function() {
7539      return this.querySelectorAll(selector);
7540    };
7541  }
7542
7543  function selection_selectAll(select) {
7544    if (typeof select !== "function") select = selectorAll(select);
7545
7546    for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
7547      for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
7548        if (node = group[i]) {
7549          subgroups.push(select.call(node, node.__data__, i, group));
7550          parents.push(node);
7551        }
7552      }
7553    }
7554
7555    return new Selection(subgroups, parents);
7556  }
7557
7558  function matcher(selector) {
7559    return function() {
7560      return this.matches(selector);
7561    };
7562  }
7563
7564  function selection_filter(match) {
7565    if (typeof match !== "function") match = matcher(match);
7566
7567    for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
7568      for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
7569        if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
7570          subgroup.push(node);
7571        }
7572      }
7573    }
7574
7575    return new Selection(subgroups, this._parents);
7576  }
7577
7578  function sparse(update) {
7579    return new Array(update.length);
7580  }
7581
7582  function selection_enter() {
7583    return new Selection(this._enter || this._groups.map(sparse), this._parents);
7584  }
7585
7586  function EnterNode(parent, datum) {
7587    this.ownerDocument = parent.ownerDocument;
7588    this.namespaceURI = parent.namespaceURI;
7589    this._next = null;
7590    this._parent = parent;
7591    this.__data__ = datum;
7592  }
7593
7594  EnterNode.prototype = {
7595    constructor: EnterNode,
7596    appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
7597    insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
7598    querySelector: function(selector) { return this._parent.querySelector(selector); },
7599    querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
7600  };
7601
7602  function constant$2(x) {
7603    return function() {
7604      return x;
7605    };
7606  }
7607
7608  var keyPrefix = "$"; // Protect against keys like “__proto__”.
7609
7610  function bindIndex(parent, group, enter, update, exit, data) {
7611    var i = 0,
7612        node,
7613        groupLength = group.length,
7614        dataLength = data.length;
7615
7616    // Put any non-null nodes that fit into update.
7617    // Put any null nodes into enter.
7618    // Put any remaining data into enter.
7619    for (; i < dataLength; ++i) {
7620      if (node = group[i]) {
7621        node.__data__ = data[i];
7622        update[i] = node;
7623      } else {
7624        enter[i] = new EnterNode(parent, data[i]);
7625      }
7626    }
7627
7628    // Put any non-null nodes that don’t fit into exit.
7629    for (; i < groupLength; ++i) {
7630      if (node = group[i]) {
7631        exit[i] = node;
7632      }
7633    }
7634  }
7635
7636  function bindKey(parent, group, enter, update, exit, data, key) {
7637    var i,
7638        node,
7639        nodeByKeyValue = {},
7640        groupLength = group.length,
7641        dataLength = data.length,
7642        keyValues = new Array(groupLength),
7643        keyValue;
7644
7645    // Compute the key for each node.
7646    // If multiple nodes have the same key, the duplicates are added to exit.
7647    for (i = 0; i < groupLength; ++i) {
7648      if (node = group[i]) {
7649        keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
7650        if (keyValue in nodeByKeyValue) {
7651          exit[i] = node;
7652        } else {
7653          nodeByKeyValue[keyValue] = node;
7654        }
7655      }
7656    }
7657
7658    // Compute the key for each datum.
7659    // If there a node associated with this key, join and add it to update.
7660    // If there is not (or the key is a duplicate), add it to enter.
7661    for (i = 0; i < dataLength; ++i) {
7662      keyValue = keyPrefix + key.call(parent, data[i], i, data);
7663      if (node = nodeByKeyValue[keyValue]) {
7664        update[i] = node;
7665        node.__data__ = data[i];
7666        nodeByKeyValue[keyValue] = null;
7667      } else {
7668        enter[i] = new EnterNode(parent, data[i]);
7669      }
7670    }
7671
7672    // Add any remaining nodes that were not bound to data to exit.
7673    for (i = 0; i < groupLength; ++i) {
7674      if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
7675        exit[i] = node;
7676      }
7677    }
7678  }
7679
7680  function selection_data(value, key) {
7681    if (!value) {
7682      data = new Array(this.size()), j = -1;
7683      this.each(function(d) { data[++j] = d; });
7684      return data;
7685    }
7686
7687    var bind = key ? bindKey : bindIndex,
7688        parents = this._parents,
7689        groups = this._groups;
7690
7691    if (typeof value !== "function") value = constant$2(value);
7692
7693    for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
7694      var parent = parents[j],
7695          group = groups[j],
7696          groupLength = group.length,
7697          data = value.call(parent, parent && parent.__data__, j, parents),
7698          dataLength = data.length,
7699          enterGroup = enter[j] = new Array(dataLength),
7700          updateGroup = update[j] = new Array(dataLength),
7701          exitGroup = exit[j] = new Array(groupLength);
7702
7703      bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
7704
7705      // Now connect the enter nodes to their following update node, such that
7706      // appendChild can insert the materialized enter node before this node,
7707      // rather than at the end of the parent node.
7708      for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
7709        if (previous = enterGroup[i0]) {
7710          if (i0 >= i1) i1 = i0 + 1;
7711          while (!(next = updateGroup[i1]) && ++i1 < dataLength);
7712          previous._next = next || null;
7713        }
7714      }
7715    }
7716
7717    update = new Selection(update, parents);
7718    update._enter = enter;
7719    update._exit = exit;
7720    return update;
7721  }
7722
7723  function selection_exit() {
7724    return new Selection(this._exit || this._groups.map(sparse), this._parents);
7725  }
7726
7727  function selection_join(onenter, onupdate, onexit) {
7728    var enter = this.enter(), update = this, exit = this.exit();
7729    enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
7730    if (onupdate != null) update = onupdate(update);
7731    if (onexit == null) exit.remove(); else onexit(exit);
7732    return enter && update ? enter.merge(update).order() : update;
7733  }
7734
7735  function selection_merge(selection) {
7736
7737    for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
7738      for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
7739        if (node = group0[i] || group1[i]) {
7740          merge[i] = node;
7741        }
7742      }
7743    }
7744
7745    for (; j < m0; ++j) {
7746      merges[j] = groups0[j];
7747    }
7748
7749    return new Selection(merges, this._parents);
7750  }
7751
7752  function selection_order() {
7753
7754    for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
7755      for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
7756        if (node = group[i]) {
7757          if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
7758          next = node;
7759        }
7760      }
7761    }
7762
7763    return this;
7764  }
7765
7766  function selection_sort(compare) {
7767    if (!compare) compare = ascending$1;
7768
7769    function compareNode(a, b) {
7770      return a && b ? compare(a.__data__, b.__data__) : !a - !b;
7771    }
7772
7773    for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
7774      for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
7775        if (node = group[i]) {
7776          sortgroup[i] = node;
7777        }
7778      }
7779      sortgroup.sort(compareNode);
7780    }
7781
7782    return new Selection(sortgroups, this._parents).order();
7783  }
7784
7785  function ascending$1(a, b) {
7786    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
7787  }
7788
7789  function selection_call() {
7790    var callback = arguments[0];
7791    arguments[0] = this;
7792    callback.apply(null, arguments);
7793    return this;
7794  }
7795
7796  function selection_nodes() {
7797    var nodes = new Array(this.size()), i = -1;
7798    this.each(function() { nodes[++i] = this; });
7799    return nodes;
7800  }
7801
7802  function selection_node() {
7803
7804    for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
7805      for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
7806        var node = group[i];
7807        if (node) return node;
7808      }
7809    }
7810
7811    return null;
7812  }
7813
7814  function selection_size() {
7815    var size = 0;
7816    this.each(function() { ++size; });
7817    return size;
7818  }
7819
7820  function selection_empty() {
7821    return !this.node();
7822  }
7823
7824  function selection_each(callback) {
7825
7826    for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
7827      for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
7828        if (node = group[i]) callback.call(node, node.__data__, i, group);
7829      }
7830    }
7831
7832    return this;
7833  }
7834
7835  function attrRemove(name) {
7836    return function() {
7837      this.removeAttribute(name);
7838    };
7839  }
7840
7841  function attrRemoveNS(fullname) {
7842    return function() {
7843      this.removeAttributeNS(fullname.space, fullname.local);
7844    };
7845  }
7846
7847  function attrConstant(name, value) {
7848    return function() {
7849      this.setAttribute(name, value);
7850    };
7851  }
7852
7853  function attrConstantNS(fullname, value) {
7854    return function() {
7855      this.setAttributeNS(fullname.space, fullname.local, value);
7856    };
7857  }
7858
7859  function attrFunction(name, value) {
7860    return function() {
vendor: 4,535 bytes, lines 7861-8026
7861      var v = value.apply(this, arguments);
7862      if (v == null) this.removeAttribute(name);
7863      else this.setAttribute(name, v);
7864    };
7865  }
7866
7867  function attrFunctionNS(fullname, value) {
7868    return function() {
7869      var v = value.apply(this, arguments);
7870      if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
7871      else this.setAttributeNS(fullname.space, fullname.local, v);
7872    };
7873  }
7874
7875  function selection_attr(name, value) {
7876    var fullname = namespace(name);
7877
7878    if (arguments.length < 2) {
7879      var node = this.node();
7880      return fullname.local
7881          ? node.getAttributeNS(fullname.space, fullname.local)
7882          : node.getAttribute(fullname);
7883    }
7884
7885    return this.each((value == null
7886        ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
7887        ? (fullname.local ? attrFunctionNS : attrFunction)
7888        : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
7889  }
7890
7891  function defaultView(node) {
7892    return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
7893        || (node.document && node) // node is a Window
7894        || node.defaultView; // node is a Document
7895  }
7896
7897  function styleRemove(name) {
7898    return function() {
7899      this.style.removeProperty(name);
7900    };
7901  }
7902
7903  function styleConstant(name, value, priority) {
7904    return function() {
7905      this.style.setProperty(name, value, priority);
7906    };
7907  }
7908
7909  function styleFunction(name, value, priority) {
7910    return function() {
7911      var v = value.apply(this, arguments);
7912      if (v == null) this.style.removeProperty(name);
7913      else this.style.setProperty(name, v, priority);
7914    };
7915  }
7916
7917  function selection_style(name, value, priority) {
7918    return arguments.length > 1
7919        ? this.each((value == null
7920              ? styleRemove : typeof value === "function"
7921              ? styleFunction
7922              : styleConstant)(name, value, priority == null ? "" : priority))
7923        : styleValue(this.node(), name);
7924  }
7925
7926  function styleValue(node, name) {
7927    return node.style.getPropertyValue(name)
7928        || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
7929  }
7930
7931  function propertyRemove(name) {
7932    return function() {
7933      delete this[name];
7934    };
7935  }
7936
7937  function propertyConstant(name, value) {
7938    return function() {
7939      this[name] = value;
7940    };
7941  }
7942
7943  function propertyFunction(name, value) {
7944    return function() {
7945      var v = value.apply(this, arguments);
7946      if (v == null) delete this[name];
7947      else this[name] = v;
7948    };
7949  }
7950
7951  function selection_property(name, value) {
7952    return arguments.length > 1
7953        ? this.each((value == null
7954            ? propertyRemove : typeof value === "function"
7955            ? propertyFunction
7956            : propertyConstant)(name, value))
7957        : this.node()[name];
7958  }
7959
7960  function classArray(string) {
7961    return string.trim().split(/^|\s+/);
7962  }
7963
7964  function classList(node) {
7965    return node.classList || new ClassList(node);
7966  }
7967
7968  function ClassList(node) {
7969    this._node = node;
7970    this._names = classArray(node.getAttribute("class") || "");
7971  }
7972
7973  ClassList.prototype = {
7974    add: function(name) {
7975      var i = this._names.indexOf(name);
7976      if (i < 0) {
7977        this._names.push(name);
7978        this._node.setAttribute("class", this._names.join(" "));
7979      }
7980    },
7981    remove: function(name) {
7982      var i = this._names.indexOf(name);
7983      if (i >= 0) {
7984        this._names.splice(i, 1);
7985        this._node.setAttribute("class", this._names.join(" "));
7986      }
7987    },
7988    contains: function(name) {
7989      return this._names.indexOf(name) >= 0;
7990    }
7991  };
7992
7993  function classedAdd(node, names) {
7994    var list = classList(node), i = -1, n = names.length;
7995    while (++i < n) list.add(names[i]);
7996  }
7997
7998  function classedRemove(node, names) {
7999    var list = classList(node), i = -1, n = names.length;
8000    while (++i < n) list.remove(names[i]);
8001  }
8002
8003  function classedTrue(names) {
8004    return function() {
8005      classedAdd(this, names);
8006    };
8007  }
8008
8009  function classedFalse(names) {
8010    return function() {
8011      classedRemove(this, names);
8012    };
8013  }
8014
8015  function classedFunction(names, value) {
8016    return function() {
8017      (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
8018    };
8019  }
8020
8021  function selection_classed(name, value) {
8022    var names = classArray(name + "");
8023
8024    if (arguments.length < 2) {
8025      var list = classList(this.node()), i = -1, n = names.length;
8026      while (++i < n) if (!list.contains(names[i])) return false;
8027      return true;
8028    }
8029
8030    return this.each((typeof value === "function"
8031        ? classedFunction : value
8032        ? classedTrue
8033        : classedFalse)(names, value));
8034  }
8035
8036  function textRemove() {
8037    this.textContent = "";
8038  }
8039
8040  function textConstant(value) {
8041    return function() {
8042      this.textContent = value;
8043    };
8044  }
8045
8046  function textFunction(value) {
8047    return function() {
8048      var v = value.apply(this, arguments);
8049      this.textContent = v == null ? "" : v;
8050    };
8051  }
8052
8053  function selection_text(value) {
8054    return arguments.length
8055        ? this.each(value == null
8056            ? textRemove : (typeof value === "function"
8057            ? textFunction
8058            : textConstant)(value))
8059        : this.node().textContent;
8060  }
8061
8062  function htmlRemove() {
8063    this.innerHTML = "";
8064  }
8065
8066  function htmlConstant(value) {
8067    return function() {
8068      this.innerHTML = value;
8069    };
8070  }
8071
8072  function htmlFunction(value) {
8073    return function() {
8074      var v = value.apply(this, arguments);
8075      this.innerHTML = v == null ? "" : v;
8076    };
8077  }
8078
8079  function selection_html(value) {
8080    return arguments.length
8081        ? this.each(value == null
8082            ? htmlRemove : (typeof value === "function"
8083            ? htmlFunction
8084            : htmlConstant)(value))
8085        : this.node().innerHTML;
8086  }
8087
8088  function raise() {
8089    if (this.nextSibling) this.parentNode.appendChild(this);
8090  }
8091
8092  function selection_raise() {
8093    return this.each(raise);
8094  }
8095
8096  function lower() {
8097    if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
8098  }
8099
8100  function selection_lower() {
8101    return this.each(lower);
8102  }
8103
8104  function selection_append(name) {
8105    var create = typeof name === "function" ? name : creator(name);
8106    return this.select(function() {
8107      return this.appendChild(create.apply(this, arguments));
8108    });
8109  }
8110
8111  function constantNull() {
8112    return null;
8113  }
8114
8115  function selection_insert(name, before) {
8116    var create = typeof name === "function" ? name : creator(name),
8117        select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
8118    return this.select(function() {
8119      return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
8120    });
8121  }
8122
8123  function remove() {
8124    var parent = this.parentNode;
8125    if (parent) parent.removeChild(this);
8126  }
8127
8128  function selection_remove() {
8129    return this.each(remove);
8130  }
8131
8132  function selection_cloneShallow() {
8133    var clone = this.cloneNode(false), parent = this.parentNode;
8134    return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
8135  }
8136
8137  function selection_cloneDeep() {
8138    var clone = this.cloneNode(true), parent = this.parentNode;
8139    return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
8140  }
8141
8142  function selection_clone(deep) {
8143    return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
8144  }
8145
8146  function selection_datum(value) {
8147    return arguments.length
8148        ? this.property("__data__", value)
8149        : this.node().__data__;
8150  }
8151
8152  var filterEvents = {};
8153
8154  var event = null;
8155
8156  if (typeof document !== "undefined") {
8157    var element = document.documentElement;
8158    if (!("onmouseenter" in element)) {
8159      filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
8160    }
8161  }
8162
8163  function filterContextListener(listener, index, group) {
8164    listener = contextListener(listener, index, group);
8165    return function(event) {
8166      var related = event.relatedTarget;
8167      if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
8168        listener.call(this, event);
8169      }
8170    };
8171  }
8172
8173  function contextListener(listener, index, group) {
8174    return function(event1) {
8175      var event0 = event; // Events can be reentrant (e.g., focus).
8176      event = event1;
8177      try {
8178        listener.call(this, this.__data__, index, group);
8179      } finally {
8180        event = event0;
8181      }
8182    };
8183  }
8184
8185  function parseTypenames$1(typenames) {
8186    return typenames.trim().split(/^|\s+/).map(function(t) {
8187      var name = "", i = t.indexOf(".");
8188      if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
8189      return {type: t, name: name};
8190    });
8191  }
8192
8193  function onRemove(typename) {
8194    return function() {
8195      var on = this.__on;
8196      if (!on) return;
8197      for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
8198        if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
8199          this.removeEventListener(o.type, o.listener, o.capture);
8200        } else {
8201          on[++i] = o;
8202        }
8203      }
8204      if (++i) on.length = i;
8205      else delete this.__on;
8206    };
8207  }
8208
8209  function onAdd(typename, value, capture) {
8210    var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
8211    return function(d, i, group) {
8212      var on = this.__on, o, listener = wrap(value, i, group);
8213      if (on) for (var j = 0, m = on.length; j < m; ++j) {
8214        if ((o = on[j]).type === typename.type && o.name === typename.name) {
8215          this.removeEventListener(o.type, o.listener, o.capture);
8216          this.addEventListener(o.type, o.listener = listener, o.capture = capture);
8217          o.value = value;
8218          return;
8219        }
8220      }
8221      this.addEventListener(typename.type, listener, capture);
8222      o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
8223      if (!on) this.__on = [o];
8224      else on.push(o);
8225    };
8226  }
8227
8228  function selection_on(typename, value, capture) {
8229    var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
8230
8231    if (arguments.length < 2) {
8232      var on = this.node().__on;
8233      if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
8234        for (i = 0, o = on[j]; i < n; ++i) {
8235          if ((t = typenames[i]).type === o.type && t.name === o.name) {
8236            return o.value;
8237          }
8238        }
8239      }
8240      return;
8241    }
8242
8243    on = value ? onAdd : onRemove;
8244    if (capture == null) capture = false;
8245    for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
8246    return this;
8247  }
8248
8249  function customEvent(event1, listener, that, args) {
8250    var event0 = event;
8251    event1.sourceEvent = event;
8252    event = event1;
8253    try {
8254      return listener.apply(that, args);
8255    } finally {
8256      event = event0;
8257    }
8258  }
8259
8260  function dispatchEvent(node, type, params) {
8261    var window = defaultView(node),
8262        event = window.CustomEvent;
8263
8264    if (typeof event === "function") {
8265      event = new event(type, params);
8266    } else {
8267      event = window.document.createEvent("Event");
8268      if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
8269      else event.initEvent(type, false, false);
8270    }
8271
8272    node.dispatchEvent(event);
8273  }
8274
8275  function dispatchConstant(type, params) {
8276    return function() {
8277      return dispatchEvent(this, type, params);
8278    };
8279  }
8280
8281  function dispatchFunction(type, params) {
8282    return function() {
8283      return dispatchEvent(this, type, params.apply(this, arguments));
8284    };
8285  }
8286
8287  function selection_dispatch(type, params) {
8288    return this.each((typeof params === "function"
8289        ? dispatchFunction
8290        : dispatchConstant)(type, params));
8291  }
8292
8293  var root = [null];
8294
8295  function Selection(groups, parents) {
8296    this._groups = groups;
8297    this._parents = parents;
8298  }
8299
8300  function selection() {
8301    return new Selection([[document.documentElement]], root);
8302  }
8303
8304  Selection.prototype = selection.prototype = {
8305    constructor: Selection,
8306    select: selection_select,
8307    selectAll: selection_selectAll,
8308    filter: selection_filter,
8309    data: selection_data,
8310    enter: selection_enter,
8311    exit: selection_exit,
8312    join: selection_join,
8313    merge: selection_merge,
8314    order: selection_order,
8315    sort: selection_sort,
8316    call: selection_call,
8317    nodes: selection_nodes,
8318    node: selection_node,
8319    size: selection_size,
8320    empty: selection_empty,
8321    each: selection_each,
8322    attr: selection_attr,
8323    style: selection_style,
8324    property: selection_property,
8325    classed: selection_classed,
8326    text: selection_text,
8327    html: selection_html,
8328    raise: selection_raise,
8329    lower: selection_lower,
8330    append: selection_append,
8331    insert: selection_insert,
8332    remove: selection_remove,
8333    clone: selection_clone,
8334    datum: selection_datum,
8335    on: selection_on,
8336    dispatch: selection_dispatch
8337  };
8338
8339  function select(selector) {
8340    return typeof selector === "string"
8341        ? new Selection([[document.querySelector(selector)]], [document.documentElement])
8342        : new Selection([[selector]], root);
8343  }
8344
8345  function sourceEvent() {
8346    var current = event, source;
8347    while (source = current.sourceEvent) current = source;
8348    return current;
8349  }
8350
8351  function point(node, event) {
8352    var svg = node.ownerSVGElement || node;
8353
8354    if (svg.createSVGPoint) {
8355      var point = svg.createSVGPoint();
8356      point.x = event.clientX, point.y = event.clientY;
8357      point = point.matrixTransform(node.getScreenCTM().inverse());
8358      return [point.x, point.y];
8359    }
8360
8361    var rect = node.getBoundingClientRect();
8362    return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
8363  }
8364
8365  function mouse(node) {
8366    var event = sourceEvent();
8367    if (event.changedTouches) event = event.changedTouches[0];
8368    return point(node, event);
8369  }
8370
8371  function touch(node, touches, identifier) {
8372    if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
8373
8374    for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
8375      if ((touch = touches[i]).identifier === identifier) {
8376        return point(node, touch);
8377      }
8378    }
8379
8380    return null;
8381  }
8382
8383  function nopropagation() {
8384    event.stopImmediatePropagation();
8385  }
8386
8387  function noevent() {
8388    event.preventDefault();
8389    event.stopImmediatePropagation();
8390  }
8391
8392  function nodrag(view) {
8393    var root = view.document.documentElement,
8394        selection = select(view).on("dragstart.drag", noevent, true);
8395    if ("onselectstart" in root) {
8396      selection.on("selectstart.drag", noevent, true);
8397    } else {
8398      root.__noselect = root.style.MozUserSelect;
8399      root.style.MozUserSelect = "none";
8400    }
8401  }
8402
8403  function yesdrag(view, noclick) {
8404    var root = view.document.documentElement,
8405        selection = select(view).on("dragstart.drag", null);
8406    if (noclick) {
8407      selection.on("click.drag", noevent, true);
8408      setTimeout(function() { selection.on("click.drag", null); }, 0);
8409    }
8410    if ("onselectstart" in root) {
8411      selection.on("selectstart.drag", null);
8412    } else {
8413      root.style.MozUserSelect = root.__noselect;
8414      delete root.__noselect;
8415    }
8416  }
8417
8418  function constant$3(x) {
8419    return function() {
8420      return x;
8421    };
8422  }
8423
8424  function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
8425    this.target = target;
8426    this.type = type;
8427    this.subject = subject;
8428    this.identifier = id;
8429    this.active = active;
8430    this.x = x;
8431    this.y = y;
8432    this.dx = dx;
8433    this.dy = dy;
8434    this._ = dispatch;
8435  }
8436
8437  DragEvent.prototype.on = function() {
8438    var value = this._.on.apply(this._, arguments);
8439    return value === this._ ? this : value;
8440  };
8441
8442  // Ignore right-click, since that should open the context menu.
8443  function defaultFilter() {
8444    return !event.ctrlKey && !event.button;
8445  }
8446
8447  function defaultContainer() {
8448    return this.parentNode;
8449  }
8450
8451  function defaultSubject(d) {
8452    return d == null ? {x: event.x, y: event.y} : d;
8453  }
8454
8455  function defaultTouchable() {
8456    return navigator.maxTouchPoints || ("ontouchstart" in this);
8457  }
8458
8459  function drag() {
8460    var filter = defaultFilter,
8461        container = defaultContainer,
8462        subject = defaultSubject,
8463        touchable = defaultTouchable,
8464        gestures = {},
8465        listeners = dispatch("start", "drag", "end"),
8466        active = 0,
8467        mousedownx,
8468        mousedowny,
8469        mousemoving,
8470        touchending,
8471        clickDistance2 = 0;
8472
8473    function drag(selection) {
8474      selection
8475          .on("mousedown.drag", mousedowned)
8476        .filter(touchable)
8477          .on("touchstart.drag", touchstarted)
8478          .on("touchmove.drag", touchmoved)
8479          .on("touchend.drag touchcancel.drag", touchended)
8480          .style("touch-action", "none")
8481          .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
8482    }
8483
8484    function mousedowned() {
8485      if (touchending || !filter.apply(this, arguments)) return;
8486      var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
8487      if (!gesture) return;
8488      select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
8489      nodrag(event.view);
8490      nopropagation();
8491      mousemoving = false;
8492      mousedownx = event.clientX;
8493      mousedowny = event.clientY;
8494      gesture("start");
8495    }
8496
8497    function mousemoved() {
8498      noevent();
8499      if (!mousemoving) {
8500        var dx = event.clientX - mousedownx, dy = event.clientY - mousedowny;
8501        mousemoving = dx * dx + dy * dy > clickDistance2;
8502      }
8503      gestures.mouse("drag");
8504    }
8505
8506    function mouseupped() {
8507      select(event.view).on("mousemove.drag mouseup.drag", null);
8508      yesdrag(event.view, mousemoving);
8509      noevent();
8510      gestures.mouse("end");
8511    }
8512
8513    function touchstarted() {
8514      if (!filter.apply(this, arguments)) return;
8515      var touches = event.changedTouches,
8516          c = container.apply(this, arguments),
8517          n = touches.length, i, gesture;
8518
8519      for (i = 0; i < n; ++i) {
8520        if (gesture = beforestart(touches[i].identifier, c, touch, this, arguments)) {
8521          nopropagation();
8522          gesture("start");
8523        }
8524      }
8525    }
8526
8527    function touchmoved() {
8528      var touches = event.changedTouches,
8529          n = touches.length, i, gesture;
8530
8531      for (i = 0; i < n; ++i) {
8532        if (gesture = gestures[touches[i].identifier]) {
8533          noevent();
8534          gesture("drag");
8535        }
8536      }
8537    }
8538
8539    function touchended() {
8540      var touches = event.changedTouches,
8541          n = touches.length, i, gesture;
8542
8543      if (touchending) clearTimeout(touchending);
8544      touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
8545      for (i = 0; i < n; ++i) {
8546        if (gesture = gestures[touches[i].identifier]) {
8547          nopropagation();
8548          gesture("end");
8549        }
8550      }
8551    }
8552
8553    function beforestart(id, container, point, that, args) {
8554      var p = point(container, id), s, dx, dy,
8555          sublisteners = listeners.copy();
8556
8557      if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
8558        if ((event.subject = s = subject.apply(that, args)) == null) return false;
8559        dx = s.x - p[0] || 0;
8560        dy = s.y - p[1] || 0;
8561        return true;
8562      })) return;
8563
8564      return function gesture(type) {
8565        var p0 = p, n;
8566        switch (type) {
8567          case "start": gestures[id] = gesture, n = active++; break;
8568          case "end": delete gestures[id], --active; // nobreak
8569          case "drag": p = point(container, id), n = active; break;
8570        }
8571        customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]);
8572      };
8573    }
8574
8575    drag.filter = function(_) {
8576      return arguments.length ? (filter = typeof _ === "function" ? _ : constant$3(!!_), drag) : filter;
8577    };
8578
8579    drag.container = function(_) {
8580      return arguments.length ? (container = typeof _ === "function" ? _ : constant$3(_), drag) : container;
8581    };
8582
8583    drag.subject = function(_) {
8584      return arguments.length ? (subject = typeof _ === "function" ? _ : constant$3(_), drag) : subject;
8585    };
8586
8587    drag.touchable = function(_) {
8588      return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$3(!!_), drag) : touchable;
8589    };
8590
8591    drag.on = function() {
8592      var value = listeners.on.apply(listeners, arguments);
8593      return value === listeners ? drag : value;
8594    };
8595
8596    drag.clickDistance = function(_) {
8597      return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2);
8598    };
8599
8600    return drag;
8601  }
8602
8603  // Copyright 2018 The Distill Template Authors
8604
8605  const T$a = Template('d-slider', `
8606<style>
8607  :host {
8608    position: relative;
8609    display: inline-block;
8610  }
8611
8612  :host(:focus) {
8613    outline: none;
8614  }
8615
8616  .background {
8617    padding: 9px 0;
8618    color: white;
8619    position: relative;
8620  }
8621
8622  .track {
8623    height: 3px;
8624    width: 100%;
8625    border-radius: 2px;
8626    background-color: hsla(0, 0%, 0%, 0.2);
8627  }
8628
8629  .track-fill {
8630    position: absolute;
8631    top: 9px;
8632    height: 3px;
8633    border-radius: 4px;
8634    background-color: hsl(24, 100%, 50%);
8635  }
8636
8637  .knob-container {
8638    position: absolute;
8639    top: 10px;
8640  }
8641
8642  .knob {
8643    position: absolute;
8644    top: -6px;
8645    left: -6px;
8646    width: 13px;
8647    height: 13px;
8648    background-color: hsl(24, 100%, 50%);
8649    border-radius: 50%;
8650    transition-property: transform;
8651    transition-duration: 0.18s;
8652    transition-timing-function: ease;
8653  }
8654  .mousedown .knob {
8655    transform: scale(1.5);
8656  }
8657
8658  .knob-highlight {
8659    position: absolute;
8660    top: -6px;
8661    left: -6px;
8662    width: 13px;
8663    height: 13px;
8664    background-color: hsla(0, 0%, 0%, 0.1);
8665    border-radius: 50%;
8666    transition-property: transform;
8667    transition-duration: 0.18s;
8668    transition-timing-function: ease;
8669  }
8670
8671  .focus .knob-highlight {
8672    transform: scale(2);
8673  }
8674
8675  .ticks {
8676    position: absolute;
8677    top: 16px;
8678    height: 4px;
8679    width: 100%;
8680    z-index: -1;
8681  }
8682
8683  .ticks .tick {
8684    position: absolute;
8685    height: 100%;
8686    border-left: 1px solid hsla(0, 0%, 0%, 0.2);
8687  }
8688
8689</style>
8690
8691  <div class='background'>
8692    <div class='track'></div>
8693    <div class='track-fill'></div>
8694    <div class='knob-container'>
8695      <div class='knob-highlight'></div>
8696      <div class='knob'></div>
8697    </div>
8698    <div class='ticks'></div>
8699  </div>
8700`);
8701
8702  // ARIA
8703  // If the slider has a visible label, it is referenced by aria-labelledby on the slider element. Otherwise, the slider element has a label provided by aria-label.
8704  // If the slider is vertically oriented, it has aria-orientation set to vertical. The default value of aria-orientation for a slider is horizontal.
8705
8706  const keyCodes = {
8707    left: 37,
8708    up: 38,
8709    right: 39,
8710    down: 40,
8711    pageUp: 33,
8712    pageDown: 34,
8713    end: 35,
8714    home: 36
8715  };
8716
8717  class Slider extends T$a(HTMLElement) {
8718
8719
8720    connectedCallback() {
8721      this.connected = true;
8722      this.setAttribute('role', 'slider');
8723      // Makes the element tab-able.
8724      if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', 0); }
8725
8726      // Keeps track of keyboard vs. mouse interactions for focus rings
8727      this.mouseEvent = false;
8728
8729      // Handles to shadow DOM elements
8730      this.knob = this.root.querySelector('.knob-container');
8731      this.background = this.root.querySelector('.background');
8732      this.trackFill = this.root.querySelector('.track-fill');
8733      this.track = this.root.querySelector('.track');
8734
8735      // Default values for attributes
8736      this.min = this.min ? this.min : 0;
8737      this.max = this.max ? this.max : 100;
8738      this.scale = linear$1().domain([this.min, this.max]).range([0, 1]).clamp(true);
8739
8740      this.origin = this.origin !== undefined ? this.origin : this.min;
8741      this.step = this.step ? this.step : 1;
8742      this.update(this.value ? this.value : 0);
8743
8744      this.ticks = this.ticks ? this.ticks : false;
8745      this.renderTicks();
8746
8747      this.drag = drag()
8748        .container(this.background)
8749        .on('start', () => {
8750          this.mouseEvent = true;
8751          this.background.classList.add('mousedown');
8752          this.changeValue = this.value;
8753          this.dragUpdate();
8754        })
8755        .on('drag', () => {
8756          this.dragUpdate();
8757        })
8758        .on('end', () => {
8759          this.mouseEvent = false;
8760          this.background.classList.remove('mousedown');
8761          this.dragUpdate();
8762          if (this.changeValue !== this.value) this.dispatchChange();
8763          this.changeValue = this.value;
8764        });
8765      this.drag(select(this.background));
8766
8767      this.addEventListener('focusin', () => {
8768        if(!this.mouseEvent) {
8769          this.background.classList.add('focus');
8770        }
8771      });
8772      this.addEventListener('focusout', () => {
8773        this.background.classList.remove('focus');
8774      });
8775      this.addEventListener('keydown', this.onKeyDown);
8776
8777    }
8778
8779    static get observedAttributes() {return ['min', 'max', 'value', 'step', 'ticks', 'origin', 'tickValues', 'tickLabels']; }
8780
8781    attributeChangedCallback(attr, oldValue, newValue) {
8782      if (isNaN(newValue) || newValue === undefined || newValue === null) return;
8783      if (attr == 'min') {
8784        this.min = +newValue;
8785        this.setAttribute('aria-valuemin', this.min);
8786      }
8787      if (attr == 'max') {
8788        this.max = +newValue;
8789        this.setAttribute('aria-valuemax', this.max);
8790      }
8791      if (attr == 'value') {
8792        this.update(+newValue);
8793      }
8794      if (attr == 'origin') {
8795        this.origin = +newValue;
8796        // this.update(this.value);
8797      }
8798      if (attr == 'step') {
8799        if (newValue > 0) {
8800          this.step = +newValue;
8801        }
8802      }
8803      if (attr == 'ticks') {
8804        this.ticks = (newValue === '' ? true : newValue);
8805      }
8806    }
8807
8808    onKeyDown(event) {
8809      this.changeValue = this.value;
8810      let stopPropagation = false;
8811      switch (event.keyCode) {
8812      case keyCodes.left:
8813      case keyCodes.down:
8814        this.update(this.value - this.step);
8815        stopPropagation = true;
8816        break;
8817      case keyCodes.right:
8818      case keyCodes.up:
8819        this.update(this.value + this.step);
8820        stopPropagation = true;
8821        break;
8822      case keyCodes.pageUp:
8823        this.update(this.value + this.step * 10);
8824        stopPropagation = true;
8825        break;
8826
8827      case keyCodes.pageDown:
8828        this.update(this.value + this.step * 10);
8829        stopPropagation = true;
8830        break;
8831      case keyCodes.home:
8832        this.update(this.min);
8833        stopPropagation = true;
8834        break;
8835      case keyCodes.end:
8836        this.update(this.max);
8837        stopPropagation = true;
8838        break;
8839      }
8840      if (stopPropagation) {
8841        this.background.classList.add('focus');
8842        event.preventDefault();
8843        event.stopPropagation();
8844        if (this.changeValue !== this.value) this.dispatchChange();
8845      }
8846    }
8847
8848    validateValueRange(min, max, value) {
8849      return Math.max(Math.min(max, value), min);
8850    }
8851
8852    quantizeValue(value, step) {
8853      return Math.round(value / step) * step;
8854    }
8855
8856    dragUpdate() {
8857      const bbox = this.background.getBoundingClientRect();
8858      const x = event.x;
8859      const width = bbox.width;
8860      this.update(this.scale.invert(x / width));
8861    }
8862
8863    update(value) {
8864      let v = value;
8865      if (this.step !== 'any') {
8866        v = this.quantizeValue(value, this.step);
8867      }
8868      v = this.validateValueRange(this.min, this.max, v);
8869      if (this.connected) {
8870        this.knob.style.left = this.scale(v) * 100 + '%';
8871        this.trackFill.style.width = this.scale(this.min + Math.abs(v - this.origin)) * 100 + '%';
8872        this.trackFill.style.left = this.scale(Math.min(v, this.origin)) * 100 + '%';
8873      }
8874      if (this.value !== v) {
8875        this.value = v;
8876        this.setAttribute('aria-valuenow', this.value);
8877        this.dispatchInput();
8878      }
8879    }
8880
8881    // Dispatches only on a committed change (basically only on mouseup).
8882    dispatchChange() {
8883      const e = new Event('change');
8884      this.dispatchEvent(e, {});
8885    }
8886
8887    // Dispatches on each value change.
8888    dispatchInput() {
8889      const e = new Event('input');
8890      this.dispatchEvent(e, {});
8891    }
8892
8893    renderTicks() {
8894      const ticksContainer = this.root.querySelector('.ticks');
8895      if (this.ticks !== false) {
8896        let tickData = [];
8897        if (this.ticks > 0) {
8898          tickData = this.scale.ticks(this.ticks);
8899        } else if (this.step === 'any') {
8900          tickData = this.scale.ticks();
8901        } else {
8902          tickData = range(this.min, this.max + 1e-6, this.step);
8903        }
8904        tickData.forEach(d => {
8905          const tick = document.createElement('div');
8906          tick.classList.add('tick');
8907          tick.style.left = this.scale(d) * 100 + '%';
8908          ticksContainer.appendChild(tick);
8909        });
8910      } else {
8911        ticksContainer.style.display = 'none';
8912      }
8913    }
8914  }
8915
8916  var logo = "<svg viewBox=\"-607 419 64 64\">\n  <path d=\"M-573.4,478.9c-8,0-14.6-6.4-14.6-14.5s14.6-25.9,14.6-40.8c0,14.9,14.6,32.8,14.6,40.8S-565.4,478.9-573.4,478.9z\"/>\n</svg>\n";
8917
8918  const headerTemplate = `
8919<style>
8920distill-header {
8921  position: relative;
8922  height: 60px;
8923  background-color: hsl(200, 60%, 15%);
8924  width: 100%;
8925  box-sizing: border-box;
8926  z-index: 2;
8927  color: rgba(0, 0, 0, 0.8);
8928  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
8929  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
8930}
8931distill-header .content {
8932  height: 70px;
8933  grid-column: page;
8934}
8935distill-header a {
8936  font-size: 16px;
8937  height: 60px;
8938  line-height: 60px;
8939  text-decoration: none;
8940  color: rgba(255, 255, 255, 0.8);
8941  padding: 22px 0;
8942}
8943distill-header a:hover {
8944  color: rgba(255, 255, 255, 1);
8945}
8946distill-header svg {
8947  width: 24px;
8948  position: relative;
8949  top: 4px;
8950  margin-right: 2px;
8951}
8952@media(min-width: 1080px) {
8953  distill-header {
8954    height: 70px;
8955  }
8956  distill-header a {
8957    height: 70px;
8958    line-height: 70px;
8959    padding: 28px 0;
8960  }
8961  distill-header .logo {
8962  }
8963}
8964distill-header svg path {
8965  fill: none;
8966  stroke: rgba(255, 255, 255, 0.8);
8967  stroke-width: 3px;
8968}
8969distill-header .logo {
8970  font-size: 17px;
8971  font-weight: 200;
8972}
8973distill-header .nav {
8974  float: right;
8975  font-weight: 300;
8976}
8977distill-header .nav a {
8978  font-size: 12px;
8979  margin-left: 24px;
8980  text-transform: uppercase;
8981}
8982</style>
8983<div class="content">
8984  <a href="/" class="logo">
8985    ${logo}
8986    Distill
8987  </a>
8988  <nav class="nav">
8989    <a href="/about/">About</a>
8990    <a href="/prize/">Prize</a>
8991    <a href="/journal/">Submit</a>
8992  </nav>
8993</div>
8994`;
8995
8996  // Copyright 2018 The Distill Template Authors
8997
8998  const T$b = Template('distill-header', headerTemplate, false);
8999
9000  class DistillHeader extends T$b(HTMLElement) {
9001
9002  }
9003
9004  // Copyright 2018 The Distill Template Authors
9005
9006  const styles$2 = `
9007<style>
9008  distill-appendix {
9009    contain: layout style;
9010  }
9011
9012  distill-appendix .citation {
9013    font-size: 11px;
9014    line-height: 15px;
9015    border-left: 1px solid rgba(0, 0, 0, 0.1);
9016    padding-left: 18px;
9017    border: 1px solid rgba(0,0,0,0.1);
9018    background: rgba(0, 0, 0, 0.02);
9019    padding: 10px 18px;
9020    border-radius: 3px;
9021    color: rgba(150, 150, 150, 1);
9022    overflow: hidden;
9023    margin-top: -12px;
9024    white-space: pre-wrap;
9025    word-wrap: break-word;
9026  }
9027
9028  distill-appendix > * {
9029    grid-column: text;
9030  }
9031</style>
9032`;
9033
9034  function appendixTemplate(frontMatter) {
9035    let html = styles$2;
9036
9037    if (typeof frontMatter.githubUrl !== 'undefined') {
9038      html += `
9039    <h3 id="updates-and-corrections">Updates and Corrections</h3>
9040    <p>`;
9041      if (frontMatter.githubCompareUpdatesUrl) {
9042        html += `<a href="${frontMatter.githubCompareUpdatesUrl}">View all changes</a> to this article since it was first published.`;
9043      }
9044      html += `
9045    If you see mistakes or want to suggest changes, please <a href="${frontMatter.githubUrl + '/issues/new'}">create an issue on GitHub</a>. </p>
9046    `;
9047    }
9048
9049    const journal = frontMatter.journal;
9050    if (typeof journal !== 'undefined' && journal.title === 'Distill') {
9051      html += `
9052    <h3 id="reuse">Reuse</h3>
9053    <p>
9053Diagrams and text are licensed under Creative Commons Attribution <a href="https://creativecommons.org/licenses/by/4.0/">CC-BY 4.0</a> with the <a class="github" href="${frontMatter.githubUrl}">source available on GitHub</a>, unless noted otherwise. The figures that have been reused from other sources don’t fall under this license and can be recognized by a note in their caption: “Figure from …”.</p>
9054    `;
9055    }
9056
9057    if (typeof frontMatter.publishedDate !== 'undefined') {
9058      html += `
9059    <h3 id="citation">Citation</h3>
9060    <p>For attribution in academic contexts, please cite this work as</p>
9061    <pre class="citation short">${frontMatter.concatenatedAuthors}, "${frontMatter.title}", Distill, ${frontMatter.publishedYear}.</pre>
9062    <p>BibTeX citation</p>
9063    <pre class="citation long">${serializeFrontmatterToBibtex(frontMatter)}</pre>
9064    `;
9065    }
9066
9067    return html;
9068  }
9069
9070  class DistillAppendix extends HTMLElement {
9071
9072    static get is() { return 'distill-appendix'; }
9073
9074    set frontMatter(frontMatter) {
9075      this.innerHTML = appendixTemplate(frontMatter);
9076    }
9077
9078  }
9079
9080  const footerTemplate = `
9081<style>
9082
9083:host {
9084  color: rgba(255, 255, 255, 0.5);
9085  font-weight: 300;
9086  padding: 2rem 0;
9087  border-top: 1px solid rgba(0, 0, 0, 0.1);
9088  background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/
9089  text-align: left;
9090  contain: content;
9091}
9092
9093.footer-container .logo svg {
9094  width: 24px;
9095  position: relative;
9096  top: 4px;
9097  margin-right: 2px;
9098}
9099
9100.footer-container .logo svg path {
9101  fill: none;
9102  stroke: rgba(255, 255, 255, 0.8);
9103  stroke-width: 3px;
9104}
9105
9106.footer-container .logo {
9107  font-size: 17px;
9108  font-weight: 200;
9109  color: rgba(255, 255, 255, 0.8);
9110  text-decoration: none;
9111  margin-right: 6px;
9112}
9113
9114.footer-container {
9115  grid-column: text;
9116}
9117
9118.footer-container .nav {
9119  font-size: 0.9em;
9120  margin-top: 1.5em;
9121}
9122
9123.footer-container .nav a {
9124  color: rgba(255, 255, 255, 0.8);
9125  margin-right: 6px;
9126  text-decoration: none;
9127}
9128
9129</style>
9130
9131<div class='footer-container'>
9132
9133  <a href="/" class="logo">
9134    ${logo}
9135    Distill
9136  </a> is dedicated to clear explanations of machine learning
9137
9138  <div class="nav">
9139    <a href="https://distill.pub/about/">About</a>
9140    <a href="https://distill.pub/journal/">Submit</a>
9141    <a href="https://distill.pub/prize/">Prize</a>
9142    <a href="https://distill.pub/archive/">Archive</a>
9143    <a href="https://distill.pub/rss.xml">RSS</a>
9144    <a href="https://github.com/distillpub">GitHub</a>
9145    <a href="https://twitter.com/distillpub">Twitter</a>
9146    &nbsp;&nbsp;&nbsp;&nbsp; ISSN 2476-0757
9147  </div>
9148
9149</div>
9150
9151`;
9152
9153  // Copyright 2018 The Distill Template Authors
9154
9155  const T$c = Template('distill-footer', footerTemplate);
9156
9157  class DistillFooter extends T$c(HTMLElement) {
9158
9159  }
9160
9161  // Copyright 2018 The Distill Template Authors
9162
9163  let templateIsLoading = false;
9164  let runlevel = 0;
9165  const initialize = function() {
9166    if (window.distill.runlevel < 1) {
9167      throw new Error("Insufficient Runlevel for Distill Template!");
9168    }
9169
9170    /* 1. Flag that we're being loaded */
9171    if ("distill" in window && window.distill.templateIsLoading) {
9172      throw new Error(
9173        "Runlevel 1: Distill Template is getting loaded more than once, aborting!"
9174      );
9175    } else {
9176      window.distill.templateIsLoading = true;
9177      console.debug("Runlevel 1: Distill Template has started loading.");
9178    }
9179
9180    /* 2. Add styles if they weren't added during prerendering */
9181    makeStyleTag(document);
9182    console.debug("Runlevel 1: Static Distill styles have been added.");
9183    console.debug("Runlevel 1->2.");
9184    window.distill.runlevel += 1;
9185
9186    /* 3. Register Controller listener functions */
9187    /* Needs to happen before components to their connected callbacks have a controller to talk to. */
9188    for (const [functionName, callback] of Object.entries(Controller.listeners)) {
9189      if (typeof callback === "function") {
9190        document.addEventListener(functionName, callback);
9191      } else {
9192        console.error("Runlevel 2: Controller listeners need to be functions!");
9193      }
9194    }
9195    console.debug("Runlevel 2: We can now listen to controller events.");
9196    console.debug("Runlevel 2->3.");
9197    window.distill.runlevel += 1;
9198
9199    /* 4. Register components */
9200    const components = [
9201      Abstract, Appendix, Article, Bibliography, Byline, Cite, CitationList, Code,
9202      Footnote, FootnoteList, FrontMatter$1, HoverBox, Title, DMath, References, TOC, Figure,
9203      Slider, Interstitial
9204    ];
9205
9206    const distillComponents = [DistillHeader, DistillAppendix, DistillFooter];
9207
9208    if (window.distill.runlevel < 2) {
9209      throw new Error("Insufficient Runlevel for adding custom elements!");
9210    }
9211    const allComponents = components.concat(distillComponents);
9212    for (const component of allComponents) {
9213      console.debug("Runlevel 2: Registering custom element: " + component.is);
9214      customElements.define(component.is, component);
9215    }
9216
9217    console.debug(
9218      "Runlevel 3: Distill Template finished registering custom elements."
9219    );
9220    console.debug("Runlevel 3->4.");
9221    window.distill.runlevel += 1;
9222
9223    // If template was added after DOMContentLoaded we may have missed that event.
9224    // Controller will check for that case, so trigger the event explicitly:
9225    if (domContentLoaded()) {
9226      Controller.listeners.DOMContentLoaded();
9227    }
9228
9229    console.debug("Runlevel 4: Distill Template initialisation complete.");
9230    window.distill.templateIsLoading = false;
9231    window.distill.templateHasLoaded = true;
9232  };
9233
9234  window.distill = { runlevel, initialize, templateIsLoading };
9235
9236  /* 0. Check browser feature support; synchronously polyfill if needed */
9237  if (Polyfills.browserSupportsAllFeatures()) {
9238    console.debug("Runlevel 0: No need for polyfills.");
9239    console.debug("Runlevel 0->1.");
9240    window.distill.runlevel += 1;
9241    window.distill.initialize();
9242  } else {
9243    console.debug("Runlevel 0: Distill Template is loading polyfills.");
9244    Polyfills.load(window.distill.initialize);
9245  }
9246
9247})));
9248//# sourceMappingURL=template.v2.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.