├── CNAME ├── docs └── CNAME ├── index.js ├── data ├── sample.csv ├── cars.csv ├── flights.csv └── notes.csv ├── test.md ├── static ├── img │ ├── contrast.svg │ ├── embed.svg │ ├── visdown.svg │ ├── share.svg │ ├── pencil.svg │ ├── datasets.svg │ ├── view.svg │ ├── twitter.svg │ ├── github.svg │ └── view-blocked.svg ├── css │ ├── visdown.css │ ├── codemirror.css │ └── github-markdown.css └── lib │ ├── markdown.min.js │ ├── highlight.pack.js │ ├── marked.min.js │ ├── vega-embed.min.js │ └── markdown.js ├── README.md ├── pages ├── annotate-layer.md ├── data-layer.md ├── interactive.md ├── intro.md ├── london.md ├── notes.md ├── start.md ├── visual-layer.md ├── composition.md ├── data.md └── interact-layer.md ├── rollup.config.js ├── LICENSE ├── js ├── visdown-vegalite-1.js ├── visdown-marked.js ├── visdown-app.js └── editor.js ├── package.json ├── src └── main.js ├── cars.csv ├── experiments ├── vega-embed.js ├── visdown.1.js └── datum.js ├── .gitignore └── index.html /CNAME: -------------------------------------------------------------------------------- 1 | visdown.com -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | visdown.com 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | export {default as visdown} from "./src/visdown"; 2 | -------------------------------------------------------------------------------- /data/sample.csv: -------------------------------------------------------------------------------- 1 | area,sales,profit 2 | North,5,2 3 | East,25,8 4 | West,15,6 5 | South,20,5 6 | Central,10,3 7 | -------------------------------------------------------------------------------- /test.md: -------------------------------------------------------------------------------- 1 | "scripts": { 2 | "pretest": "rm -rf build && mkdir build && rollup -f umd -n visdown -o build/visdown.js -- index.js", 3 | "prepare": "uglifyjs build/visdown.js -c -m -o build/visdown.min.js", 4 | "postpublish": "zip -j build/visdown.zip -- LICENSE README.md build/visdown.js build/visdown.min.js" 5 | }, -------------------------------------------------------------------------------- /static/img/contrast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /static/img/embed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /static/img/visdown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vd 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Visdown 2 | 3 | Make visualisation using markdown 4 | 5 | Demo -> [http://visdown.com/](http://visdown.com/) 6 | 7 | Allows you to write *json specification* in simple *yaml* and uses **marked** and **vega-lite** (or vega) to convert those specific code blocks in to svg. 8 | 9 | - yaml -> json (using [yaml.js](https://github.com/jeremyfa/yaml.js)) 10 | - json -> vega-lite -> svg (using [vegalite.js](https://vega.github.io/vega-lite/)) 11 | - markdown -> html (using [marked.js](https://github.com/marked) 12 | 13 | 14 | -------------------------------------------------------------------------------- /static/img/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /static/img/pencil.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /static/img/datasets.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /pages/annotate-layer.md: -------------------------------------------------------------------------------- 1 | # Annotate Layer 2 | 3 | - Title and Labels 4 | - Axis and Tick marks 5 | - Guides e.g. Legends 6 | - Grids and Reference marks 7 | - Text Annotation 8 | - Story Elements 9 | 10 | 11 | ```vis 12 | data: 13 | url: data/notes.csv 14 | mark: area 15 | encoding: 16 | x: 17 | field: year 18 | type: temporal 19 | axis: 20 | format: %Y 21 | labelAngle: 0 22 | title: Year 23 | titleFontSize: 12 24 | y: 25 | aggregate: sum 26 | field: money 27 | type: quantitative 28 | axis: 29 | title: Notes in Circulation (Value ₹ Billions) 30 | titleFontSize: 12 31 | color: 32 | field: denom 33 | type: nominal 34 | 35 | config: 36 | cell: 37 | width: 400 38 | height: 300 39 | ``` 40 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import pkg from './package.json'; 3 | 4 | export default [ 5 | // browser-friendly UMD build 6 | { 7 | input: 'src/main.js', 8 | output: { 9 | name: 'visdown', 10 | file: pkg.browser, 11 | format: 'umd' 12 | }, 13 | plugins: [ 14 | resolve(), // so Rollup can find `dependencies` 15 | ] 16 | }, 17 | 18 | // CommonJS (for Node) and ES module (for bundlers) build. 19 | // (We could have three entries in the configuration array 20 | // instead of two, but it's quicker to generate multiple 21 | // builds from a single configuration where possible, using 22 | // an array for the `output` option, where we can specify 23 | // `file` and `format` for each target) 24 | { 25 | input: 'src/main.js', 26 | external: ['ms'], 27 | output: { 28 | file: pkg.module, 29 | format: 'es' 30 | } 31 | } 32 | ]; -------------------------------------------------------------------------------- /static/img/view.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /static/img/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Amit Kapoor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pages/data-layer.md: -------------------------------------------------------------------------------- 1 | # Data Layer 2 | 3 | ## Types of Variables 4 | - Categorical: Nominal, Ordinal 5 | - Continuous: Temporal, Quantitative 6 | 7 | ```vis 8 | data(data/notes.csv) 9 | line(x=year:T, y=money:Q, color=denom:N) 10 | ``` 11 | 12 | ## Transforming the Data 13 | - Filter, Sort 14 | - Aggregate (e.g. min, max, sum, ...) 15 | - Bin 16 | - Derive (new variable) 17 | - Sample 18 | - Reshape (e.g. tall <-> wide) 19 | 20 | 21 | ### Filter 22 | 23 | Lets filter this data for denominations greater than INR 10. 24 | 25 | ```vis 26 | data(data/notes.csv) 27 | filter(datum.value > 10) 28 | line(x=year:T, y=money:Q, color=denom:N) 29 | ``` 30 | 31 | ### Aggregate 32 | 33 | You can aggregate on a particular variable to do basic statistical operations like mean, sum, quantile etc. 34 | 35 | ```vis 36 | data(data/notes.csv) 37 | area(x=year:T, y=sum(money:Q), color=denom:N) 38 | ``` 39 | 40 | ### Bins 41 | 42 | Binning is a technique for grouping quantitative, continuous data values of a particular field into smaller number of “bins” 43 | 44 | ```vis 45 | data(data/notes.csv) 46 | bar(x=bin(money:Q), y=count:Q, color=denom:N) 47 | ``` 48 | -------------------------------------------------------------------------------- /js/visdown-vegalite-1.js: -------------------------------------------------------------------------------- 1 | window.onload = function () { 2 | 3 | // Start a new marked instance and renderer 4 | var marked = window.marked; 5 | var renderer = new marked.Renderer(); 6 | var counter = 0; 7 | 8 | // Render the ```vis as a vega-lite chart 9 | renderer.code = function (code, lang, escaped) { 10 | if (lang == "vis") { 11 | var jsonVis = YAML.parse(code); 12 | var embedSpec = {mode: "vega-lite", spec: jsonVis, renderer: "svg" }; 13 | counter++; 14 | el = "#vis-" + counter; 15 | vg.embed(el, embedSpec, function(error, result) {}); 16 | htmlChart = "
"; 17 | return htmlChart; 18 | } 19 | var result = marked.Renderer.prototype.code.call(this, code, lang, escaped); 20 | return result; 21 | }; 22 | 23 | // Convert from Markdown to HTML 24 | var input = document.querySelector("#visdown-input"); 25 | var output = document.querySelector("#visdown-output"); 26 | 27 | window.visdownVega = function () { 28 | console.log('visdownVega'); 29 | var markdownText = input.value; 30 | output.innerHTML = marked(markdownText, { renderer: renderer }); 31 | } 32 | visdownVega() 33 | 34 | } 35 | -------------------------------------------------------------------------------- /pages/interactive.md: -------------------------------------------------------------------------------- 1 | 2 | ```vis 3 | data(data/cars.csv) | point(x=kmpl:Q, y=price:Q) 4 | ``` 5 | 6 | # Testing Grammar 7 | 8 |
9 |
var x = 2
10 |
11 | 12 |
13 |
var x = 2
14 |
15 | 16 | This is [an example] [id] reference-style link. 17 | 18 | [id]: http://example.com/ "Optional Title Here" 19 | 20 | 21 | Test 1 22 | 23 | ![](http://amitkaps.com) 24 | 25 | - One 26 | - Two 27 | - Three 28 | 29 | There is a test **bold** here 30 | 31 | ```vis 32 | data(data/cars.csv) | point(x=kmpl:Q, y=price:Q) 33 | ``` 34 | 35 | This is [an example] [id] reference-style link. 36 | 37 | [id]: http://example.com/ 38 | 39 | And this is another code element 40 | 41 | ```vis 42 | data(data/cars.csv) | point(x=kmpl:Q, y=price:Q, color=bhp:Q) 43 | ``` 44 | hello 45 | 46 | ```vis 47 | data(data/cars.csv) | point(x=kmpl:Q, y=price:Q, color=bhp:Q) 48 | ``` 49 | 50 | ```js 51 | var x = 2 52 | ``` 53 | 54 | And another vis here 55 | 56 | ## Another Vis 57 | 58 | ```vis 59 | data(data/cars.csv) | point(x=kmpl:Q, y=price:Q) 60 | ``` 61 | 62 | And here is more text -------------------------------------------------------------------------------- /static/img/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "visdown", 3 | "version": "0.1.0", 4 | "description": "Make Visualisations using Markdown", 5 | "keywords": [ 6 | "markdown", 7 | "visualisation", 8 | "interaction", 9 | "vega-lite", 10 | "analytics" 11 | ], 12 | "author": "Amit Kapoor (http://amitkaps.com)", 13 | "license": "MIT", 14 | "main": "build/visdown.js", 15 | "homepage": "https://github.com/amitkaps/visdown", 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/amitkaps/visdown.git" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/amitkaps/visdown/issues" 22 | }, 23 | "scripts": { 24 | "pretest": "rm -rf build && mkdir build && rollup -f umd -n visdown -o build/visdown.js -- index.js", 25 | "test": "tape 'test/**/*-test.js'", 26 | "prepublish": "npm run test && uglifyjs build/visdown.js -c -m -o build/visdown.min.js", 27 | "postpublish": "zip -j build/visdown.zip -- LICENSE README.md build/visdown.js build/visdown.min.js" 28 | }, 29 | "dependencies": { 30 | "yamljs": "^0.3.0", 31 | "marked": "^2.0.3", 32 | "vega": "^5.20.2", 33 | "vega-lite": "^5.1.0", 34 | "vega-embed": "^6.17.0" 35 | }, 36 | "devDependencies": { 37 | "rollup": "^2.45.2", 38 | "tape": "^5.2.2", 39 | "uglify-js": "^3.13.4" 40 | }, 41 | "directories": { 42 | "doc": "docs" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /pages/intro.md: -------------------------------------------------------------------------------- 1 | # Visdown 2 | 3 | **Make visualisations using only markdown** 4 | 5 | Write visualisation using a simple declarative markup like you would write code. Just wrap it in fenced block (three backticks) and mark the language as `vis`. 6 | 7 | *Make simple static visualisations* 8 | 9 | ```vis 10 | data: 11 | url: data/cars.csv 12 | mark: point 13 | encoding: 14 | x: 15 | field: kmpl 16 | type: quantitative 17 | y: 18 | field: price 19 | type: quantitative 20 | ``` 21 | 22 | Visdown is based on the grammar of interactive graphic (vega-lite) which allows you to specify the visualisation including interactions in a declarative fashion. 23 | 24 | *Make interactive visualisations* 25 | 26 | Select the circles with the mouse 27 | 28 | ```vis 29 | data: 30 | url: "data/cars.csv" 31 | mark: circle 32 | selection: 33 | brush: 34 | type: interval 35 | encoding: 36 | x: 37 | type: quantitative 38 | field: kmpl 39 | scale: 40 | domain: [12,25] 41 | y: 42 | type: quantitative 43 | field: price 44 | scale: 45 | domain: [100,900] 46 | color: 47 | condition: 48 | selection: brush 49 | field: type 50 | type: nominal 51 | value: grey 52 | size: 53 | type: quantitative 54 | field: bhp 55 | width: 450 56 | height: 300 57 | ``` 58 | 59 | --- 60 | Handcrafted by [Amit Kapoor](http://amitkaps.com) 61 | -------------------------------------------------------------------------------- /js/visdown-marked.js: -------------------------------------------------------------------------------- 1 | window.onload = function () { 2 | 3 | // Start a new marked instance and renderer 4 | var marked = window.marked; 5 | var renderer = new marked.Renderer(); 6 | var counter = 0; 7 | var specs = []; 8 | var opts = {"mode": "vega-lite", "renderer": "svg" }; 9 | 10 | 11 | // Render the ```vis as a div and save the json spec 12 | renderer.code = function (code, lang, escaped) { 13 | if (lang == "vis") { 14 | jsonVis = YAML.parse(code); 15 | specs.push(jsonVis); 16 | counter++; 17 | el = "#vis-" + counter; 18 | htmlChart = "
"; 19 | return htmlChart; 20 | } 21 | var result = marked.Renderer.prototype.code.call(this, code, lang, escaped); 22 | return result; 23 | }; 24 | 25 | // Render the vega-lite chart for each json spec 26 | vegaliteRender = function (err, content) { 27 | for (var i=0; i < specs.length; i++) { 28 | j = i + 1; 29 | el = "#vis-" + j; 30 | vega.embed(el, specs[i], opts); 31 | } 32 | return content; 33 | }; 34 | 35 | 36 | // Convert from Markdown to HTML 37 | var input = document.querySelector("#visdown-input"); 38 | var output = document.querySelector("#visdown-output"); 39 | 40 | window.visdown = function () { 41 | console.log('visdown'); 42 | var markdownText = input.value; 43 | output.innerHTML = marked(markdownText, { renderer: renderer}); 44 | vegaliteRender(); 45 | } 46 | visdown() 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /static/img/view-blocked.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * visdown - a parser for vega-lite vis in markdown 3 | * Copyright (c) 2016-2018, Amit Kapoor. (MIT Licensed) 4 | * https://github.com/amitkaps/visdown 5 | */ 6 | 7 | 8 | // Need to have vega and vega-lite as dependencies 9 | // const vega = window.vega 10 | // const vl = window.vl 11 | 12 | 13 | // import vega from 'vega' 14 | // import vega-lite as vl from 'vega-lite' 15 | import marked from 'marked' 16 | import YAML from 'yamljs' 17 | import vegaEmbed from 'vega-embed' 18 | 19 | // Start Marked Renderer 20 | const renderer = new marked.Renderer(); 21 | marked.setOptions({ 22 | renderer: renderer, 23 | gfm: true, 24 | tables: true, 25 | }); 26 | 27 | const opts = { 28 | "mode": "vega-lite", 29 | "renderer": "svg", 30 | "actions": {export: false, source: false, editor: false} 31 | }; 32 | 33 | 34 | //Render the vega-lite chart for each json spec 35 | function _render(element) { 36 | let specs = element.getElementsByClassName('lang-vis') 37 | let num = specs.length; 38 | for (var i=0; i < num; i++) { 39 | let el = "#vis-" + i; 40 | let jsonSpec = YAML.parse(specs[i].textContent) 41 | console.log(jsonSpec) 42 | //console.log(vl.compile(jsonVis).spec == undefined) 43 | htmlString = "
" 44 | specs[i].parentNode.insertAdjacentHTML('beforebegin', htmlString); 45 | specs[i].parentNode.style.display = 'none'; 46 | vegaEmbed(el, jsonSpec, opts); 47 | }; 48 | }; 49 | 50 | function visdown(input, element) { 51 | console.log('visdown'); 52 | let visdownText = input; 53 | element.innerHTML = marked(visdownText); 54 | _render(element); 55 | } -------------------------------------------------------------------------------- /cars.csv: -------------------------------------------------------------------------------- 1 | brand,model,price,kmpl,bhp,type 2 | Chevrolet,Beat,421,18.6,79,Hatchback 3 | Chevrolet,Sail,551,18.2,82,Sedan 4 | Chevrolet,Sail Hatchback,468,18.2,82,Hatchback 5 | Chevrolet,Spark,345,16.2,62,Hatchback 6 | Fiat,Linea Classic,612,14.9,89,Sedan 7 | Fiat,Linea,700,15.7,112,Sedan 8 | Fiat,Punto Evo,499,15.8,67,Hatchback 9 | Ford,Classic,506,14.1,100,Sedan 10 | Ford,Figo,414,15.3,70,Hatchback 11 | Honda,Amaze,519,18,87,Sedan 12 | Honda,Brio,421,19.4,87,Hatchback 13 | Hyundai,EON,302,21.1,55,Hatchback 14 | Hyundai,i10,418,19.8,68,Hatchback 15 | Hyundai,i20,523,18.6,82,Hatchback 16 | Hyundai,Verna,774,17.4,106,Sedan 17 | Hyundai,Xcent,496,19.1,82,Sedan 18 | Suzuki,Alto,315,24.1,67,Hatchback 19 | Suzuki,Alto 800,248,22.7,47,Hatchback 20 | Suzuki,Celerio,392,23.1,67,Hatchback 21 | Suzuki,Ciaz,725,20.7,91,Sedan 22 | Suzuki,Estilo,338,19,67,Hatchback 23 | Suzuki,Ritz,442,18.5,86,Hatchback 24 | Suzuki,Swift,462,20.4,83,Hatchback 25 | Suzuki,Swift DZire,508,19.1,86,Sedan 26 | Suzuki,SX4,715,16.5,103,Sedan 27 | Suzuki,Wagon-R,363,20.5,67,Hatchback 28 | Nissan,Datsun GO,312,20.6,67,Hatchback 29 | Nissan,Micra,413,19.5,67,Hatchback 30 | Nissan,Sunny,699,16.9,98,Sedan 31 | Renault,Pulse,446,18,74,Hatchback 32 | Renault,Scala,724,16.9,98,Sedan 33 | San,Storm,595,16,59,Sedan 34 | Skoda,Fabia,503,16.4,75,Hatchback 35 | Skoda,Rapid,756,15,104,Sedan 36 | Tata,Indigo,499,14,65,Sedan 37 | Tata,Nano,199,23.9,38,Hatchback 38 | Tata,Zest,481,17.6,89,Sedan 39 | Toyota,Etios,603,16.8,89,Sedan 40 | Toyota,Etios Liva,500,17.7,79,Hatchback 41 | Volkswagen,Polo,535,16.5,74,Hatchback 42 | Volkswagen,Up,360,21,74,Hatchback 43 | Volkswagen,Vento,785,16.1,104,Sedan 44 | -------------------------------------------------------------------------------- /data/cars.csv: -------------------------------------------------------------------------------- 1 | brand,model,price,kmpl,bhp,type 2 | Chevrolet,Beat,421,18.6,79,Hatchback 3 | Chevrolet,Sail,551,18.2,82,Sedan 4 | Chevrolet,Sail Hatchback,468,18.2,82,Hatchback 5 | Chevrolet,Spark,345,16.2,62,Hatchback 6 | Fiat,Linea Classic,612,14.9,89,Sedan 7 | Fiat,Linea,700,15.7,112,Sedan 8 | Fiat,Punto Evo,499,15.8,67,Hatchback 9 | Ford,Classic,506,14.1,100,Sedan 10 | Ford,Figo,414,15.3,70,Hatchback 11 | Honda,Amaze,519,18,87,Sedan 12 | Honda,Brio,421,19.4,87,Hatchback 13 | Hyundai,EON,302,21.1,55,Hatchback 14 | Hyundai,i10,418,19.8,68,Hatchback 15 | Hyundai,i20,523,18.6,82,Hatchback 16 | Hyundai,Verna,774,17.4,106,Sedan 17 | Hyundai,Xcent,496,19.1,82,Sedan 18 | Suzuki,Alto,315,24.1,67,Hatchback 19 | Suzuki,Alto 800,248,22.7,47,Hatchback 20 | Suzuki,Celerio,392,23.1,67,Hatchback 21 | Suzuki,Ciaz,725,20.7,91,Sedan 22 | Suzuki,Estilo,338,19,67,Hatchback 23 | Suzuki,Ritz,442,18.5,86,Hatchback 24 | Suzuki,Swift,462,20.4,83,Hatchback 25 | Suzuki,Swift DZire,508,19.1,86,Sedan 26 | Suzuki,SX4,715,16.5,103,Sedan 27 | Suzuki,Wagon-R,363,20.5,67,Hatchback 28 | Nissan,Datsun GO,312,20.6,67,Hatchback 29 | Nissan,Micra,413,19.5,67,Hatchback 30 | Nissan,Sunny,699,16.9,98,Sedan 31 | Renault,Pulse,446,18,74,Hatchback 32 | Renault,Scala,724,16.9,98,Sedan 33 | San,Storm,595,16,59,Sedan 34 | Skoda,Fabia,503,16.4,75,Hatchback 35 | Skoda,Rapid,756,15,104,Sedan 36 | Tata,Indigo,499,14,65,Sedan 37 | Tata,Nano,199,23.9,38,Hatchback 38 | Tata,Zest,481,17.6,89,Sedan 39 | Toyota,Etios,603,16.8,89,Sedan 40 | Toyota,Etios Liva,500,17.7,79,Hatchback 41 | Volkswagen,Polo,535,16.5,74,Hatchback 42 | Volkswagen,Up,360,21,74,Hatchback 43 | Volkswagen,Vento,785,16.1,104,Sedan -------------------------------------------------------------------------------- /experiments/vega-embed.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * Embed a Vega-lite visualization component in a web page. 5 | * This function will either throw an exception, or return a promise 6 | * 7 | * @param el DOM element in which to place component (DOM node or CSS selector) 8 | * @param spec String : A URL string from which to load the Vega specification. 9 | Object : The Vega-Lite specification as a parsed JSON object. 10 | * @param opt A JavaScript object containing options for embedding. 11 | */ 12 | function embed(el, spec, opt) { 13 | opt = opt || {}; 14 | var renderer = opt.renderer || 'canvas'; 15 | var runtime = vl.compile(vljson).spec; // may throw an Error if parsing fails 16 | var view = new vega.View(runtime) 17 | .logLevel(vega.Warn) // set view logging level 18 | .initialize(document.querySelector(el)) // set parent DOM element 19 | .renderer(renderer) // set render type (defaults to 'canvas') 20 | .run(); // update and render the view 21 | return Promise.resolve({view: view}); 22 | } 23 | 24 | 25 | /** 26 | * Embed a Vega-lite visualization component in a web page. 27 | * 28 | * @param el DOM element in which to place component (DOM node or CSS selector) 29 | * @param spec String : A URL string from which to load the Vega-lite specification. 30 | * Object : The Vega/Vega-Lite specification as a parsed JSON object. 31 | * @param opt A JavaScript object containing options for embedding. 32 | */ 33 | function embedMain(el, spec, opt) { 34 | // Ensure any exceptions will be properly handled 35 | return new Promise((accept, reject) => { 36 | embed(el, spec, opt).then(accept, reject); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /pages/london.md: -------------------------------------------------------------------------------- 1 | # London Dataset 2 | 3 | This dataset was is about flight punctuality from London Airport to 5 major US airports 4 | 5 | | source| dest | airline | flights| onTimePerf| delayAvg | year | 6 | |:------|:-----|:--------|-------:|----------:|---------:|-----:| 7 | | LHR   | ORD |  AA | 2490 |    63.33 | 21.11 | 2010 | 8 | | LHR | ORD |  BA | 1413 |   57.36 | 23.30 | 2010 | 9 | | LHR | ORD |  UA  | 2105 |   73.24 | 14.57 | 2010 | 10 | | LHR | ORD |  VS | 218 |   77.06 | 11.10 | 2010 | 11 | | ...   | ...  |  ...  | ... |  ...  |  ... | ... | 12 | | LHR | IAD |  US | 2134 |   82.05 | 13.24 | 2016 | 13 | | LHR | IAD |  VS | 699 |   84.69 | 8.02 | 2016 | 14 | | LCY | JFK |  BA | 921 |   90.01 | 5.26 | 2016 | 15 | | LTN | EWR |  DJT | 333 |   87.05 | 8.44 | 2016 | 16 | 17 | Metadata 18 | - Observations `(n)` : 157 19 | - Features `(p)` : 7 20 | - `source` : The source IATA airport code 21 | - `dest` : The destination IATA airport code 22 | - `airline` : The two letter IATA code for the airline 23 | - `flights` : The number of flights in that year 24 | - `onTimePerf` : The precentage of flights on-time in that route 25 | - `delayAvg` : The average delay in minutes for that route and airline 26 | - `year`: The year of data 27 | 28 | - Source: It is adapted from flight punctuality statistics from the London Civil Aviation Authority 29 | 30 | 31 | Make simple visualisations 32 | 33 | ```vis 34 | data: 35 | url: "data/london.csv" 36 | transform: 37 | - 38 | filter: datum.year == 2016 39 | mark: rect 40 | encoding: 41 | x: 42 | type: nominal 43 | field: source 44 | y: 45 | type: nominal 46 | field: dest 47 | color: 48 | type: quantitative 49 | field: flights 50 | aggregate: sum 51 | ``` 52 | -------------------------------------------------------------------------------- /pages/notes.md: -------------------------------------------------------------------------------- 1 | # Notes Dataset 2 | 3 | This dataset was inspired by the demonetisation of INR 500 and INR 1000 notes in India conducted in 2016. 4 | 5 | | year | type   |  denom |  value | money | number | 6 | |--------:|:-------|-------:|-------:|--------:|-------:| 7 | | 1977    | Notes  |   0001 |    1 | 2.72 |  2.720 | 8 | | 1977 | Notes |   1000 |   1000 | 0.55 |  0.001 | 9 | | 1977 | Notes  |   0002 |   2 | 1.48 |  0.740 | 10 | | 1977 | Notes  |   0050 |   50 | 9.95 |  0.199 | 11 | | ...     | ...    |   ... |    ... |  ... |    ... | 12 | | 2015    | Notes  |   0500 |    500 | 7853.75 | 15.708 | 13 | | 2015 | Notes |   0001 |   1 | 3.09 |  3.090 | 14 | | 2015 | Notes  |   0010 |   10 | 320.15 | 32.015 | 15 | | 2015 | Notes  |   1000 |   1000 | 6325.68 |  6.326 | 16 | 17 | Metadata 18 | - Observations `(n)` : 351 19 | - Features `(p)` : 6 20 | - `year` : The year of circulation 21 | - `type` : The type of currency 22 | - `denom` : The denomination of the currency 23 | - `value` : The face value of the currency 24 | - `money` : The monetary value of currency in circulation (in INR Billion) 25 | - `number`: The number of currency in circulation (in INR Billion) 26 | 27 | - Source: It is taken from Reserve Bank of India’s - Handbook of Statistics on Indian Economy 2016. Within it, Table 160 deals with [Notes and Coins in Circulation](https://www.rbi.org.in/scripts/PublicationsView.aspx?id=17293) and this dataset is only about the Notes circulation. 28 | 29 | 30 | Make simple visualisations 31 | 32 | ```vis 33 | data: 34 | url: data/notes.csv 35 | transform: 36 | - 37 | filter: datum.year == 2015 38 | mark: bar 39 | encoding: 40 | x: 41 | type: nominal 42 | field: denom 43 | y: 44 | type: quantitative 45 | field: money 46 | color: 47 | type: nominal 48 | field: denom 49 | ``` 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/node,macos,jekyll 2 | 3 | ### Jekyll ### 4 | _site/ 5 | .sass-cache/ 6 | .jekyll-metadata 7 | 8 | ### macOS ### 9 | *.DS_Store 10 | .AppleDouble 11 | .LSOverride 12 | 13 | # Icon must end with two \r 14 | Icon 15 | 16 | # Thumbnails 17 | ._* 18 | 19 | # Files that might appear in the root of a volume 20 | .DocumentRevisions-V100 21 | .fseventsd 22 | .Spotlight-V100 23 | .TemporaryItems 24 | .Trashes 25 | .VolumeIcon.icns 26 | .com.apple.timemachine.donotpresent 27 | 28 | # Directories potentially created on remote AFP share 29 | .AppleDB 30 | .AppleDesktop 31 | Network Trash Folder 32 | Temporary Items 33 | .apdisk 34 | 35 | ### Node ### 36 | # Logs 37 | logs 38 | *.log 39 | npm-debug.log* 40 | yarn-debug.log* 41 | yarn-error.log* 42 | 43 | # Runtime data 44 | pids 45 | *.pid 46 | *.seed 47 | *.pid.lock 48 | 49 | # Directory for instrumented libs generated by jscoverage/JSCover 50 | lib-cov 51 | 52 | # Coverage directory used by tools like istanbul 53 | coverage 54 | 55 | # nyc test coverage 56 | .nyc_output 57 | 58 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 59 | .grunt 60 | 61 | # Bower dependency directory (https://bower.io/) 62 | bower_components 63 | 64 | # node-waf configuration 65 | .lock-wscript 66 | 67 | # Compiled binary addons (http://nodejs.org/api/addons.html) 68 | build/Release 69 | 70 | # Dependency directories 71 | node_modules/ 72 | jspm_packages/ 73 | 74 | # Typescript v1 declaration files 75 | typings/ 76 | 77 | # Optional npm cache directory 78 | .npm 79 | 80 | # Optional eslint cache 81 | .eslintcache 82 | 83 | # Optional REPL history 84 | .node_repl_history 85 | 86 | # Output of 'npm pack' 87 | *.tgz 88 | 89 | # Yarn Integrity file 90 | .yarn-integrity 91 | 92 | # dotenv environment variables file 93 | .env 94 | 95 | 96 | 97 | # End of https://www.gitignore.io/api/node,macos,jekyll -------------------------------------------------------------------------------- /experiments/visdown.1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * visdown - a parser for vega-lite vis in markdown 3 | * Copyright (c) 2016-2018, Amit Kapoor. (MIT Licensed) 4 | * https://github.com/amitkaps/visdown 5 | */ 6 | 7 | ;(function() { 8 | 9 | // Need to have vega, vega-lite and marked as dependencies 10 | // const vega = window.vega 11 | // const vl = window.vl 12 | // const marked = window.marked 13 | // const YAML = window.yaml 14 | 15 | 16 | // Start Marked Renderer 17 | const renderer = new marked.Renderer(); 18 | marked.setOptions({ 19 | renderer: renderer, 20 | gfm: true, 21 | tables: true, 22 | }); 23 | 24 | 25 | const opts = { 26 | "mode": "vega-lite", 27 | "renderer": "svg", 28 | "actions": {export: false, source: false, editor: false} 29 | }; 30 | 31 | 32 | //Render the vega-lite chart for each json spec 33 | function _render(element) { 34 | let specs = element.getElementsByClassName('lang-vis') 35 | let num = specs.length; 36 | for (var i=0; i < num; i++) { 37 | let el = "#vis-" + i; 38 | let jsonSpec = YAML.parse(specs[i].textContent) 39 | console.log(jsonSpec) 40 | //console.log(vl.compile(jsonVis).spec == undefined) 41 | htmlString = "
" 42 | specs[i].parentNode.insertAdjacentHTML('beforebegin', htmlString); 43 | specs[i].parentNode.style.display = 'none'; 44 | vegaEmbed(el, jsonSpec, opts); 45 | }; 46 | }; 47 | 48 | function visdown(input, element) { 49 | console.log('visdown'); 50 | let visdownText = input; 51 | element.innerHTML = marked(visdownText); 52 | _render(element); 53 | } 54 | 55 | if (typeof module !== 'undefined' && typeof exports === 'object') { 56 | module.exports = visdown; 57 | } else if (typeof define === 'function' && define.amd) { 58 | define(function() { return visdown; }); 59 | } else { 60 | this.visdown = visdown; 61 | } 62 | 63 | }).call(function() { 64 | return this || (typeof window !== 'undefined' ? window : global); 65 | }()); -------------------------------------------------------------------------------- /pages/start.md: -------------------------------------------------------------------------------- 1 | # Starting with Visdown 2 | 3 | This is a simple introduction to start using Visdown. 4 | 5 | ## Basic 6 | Visdown here is a markdown application and it will render the markdown as html in the view block. 7 | 8 | **This is an introduction to Visdown** 9 | 10 | ``` 11 | Hello world! 12 | ``` 13 | 14 | The one and only modification to markdown is to add static and interactive visualisation to the html. This is done by creating a new visualisation in fenced block (three backticks) and marking the language as 'vis'. 15 | 16 | ```vis 17 | data(data/london.csv) 18 | filter(datum.year == 2016) 19 | rect(x=source:N, y=dest:N, color=flights:Q:sum) 20 | ``` 21 | 22 | Lets build this visualisation step by step 23 | 24 | ## Data and Marks 25 | 26 | We can add the data in directly, csv or json using the `data` entry and then encode it using `mark` 27 | 28 | ```vis 29 | data(data/london.csv) 30 | rect() 31 | ``` 32 | 33 | ## Encoding 34 | 35 | Right now every field is mapped to this one rectangle. We need to add the encoding channel to define which field we want to show. So lets add `x`channel to encoding. 36 | 37 | ```vis 38 | data(data/london.csv) 39 | rect(x=source:N) 40 | ``` 41 | 42 | Now we can see the four rect corresponding to the 4 source destination that are there. Now if we add a 'y' channel to the mix, we will start to see the rect corresponding to the `dest` value in it. 43 | 44 | ```vis 45 | data(data/london.csv) 46 | rect(x=source:N, y=dest:N) 47 | ``` 48 | 49 | We can add the `color` channel to color them by the `flights` 50 | 51 | ```vis 52 | data(data/london.csv) 53 | rect(x=source:N, y=dest:N, color=flights:Q) 54 | ``` 55 | 56 | However we need to do color them by the sum of number of flights 57 | 58 | ```vis 59 | data(data/london.csv) 60 | rect(x=source:N, y=dest:N, color=flights:Q:sum) 61 | ``` 62 | 63 | ## Transform 64 | 65 | We want to show this chart for one particular `year`, which is 2016. So we need to transform the data and filter it for only that year. Lets do that. 66 | 67 | ```vis 68 | data(data/london.csv) 69 | filter(datum.year == 2016) 70 | rect(x=source:N, y=dest:N, color=flights:Q:sum) 71 | ``` 72 | 73 | -------------------------------------------------------------------------------- /js/visdown-app.js: -------------------------------------------------------------------------------- 1 | window.onload = function () { 2 | 3 | var sc = document.getElementById("visdown-input"); 4 | var content = sc.textContent || sc.innerText || sc.innerHTML; 5 | 6 | window.editor = CodeMirror.fromTextArea(sc, { 7 | lineNumbers: false, 8 | lineWrapping: true, 9 | mode: "markdown", 10 | value: content, 11 | }); 12 | 13 | var marked = window.marked; 14 | 15 | // var md = new markdownit().use(markdownitIncrementalDOM) 16 | specs = []; 17 | var opts = {"mode": "vega-lite", 18 | "renderer": "svg", 19 | "actions": {export: false, source: false, editor: false} 20 | }; 21 | 22 | //Render the vega-lite chart for each json spec 23 | vegaliteRender = function () { 24 | specs = document.getElementsByClassName('lang-vis') 25 | var num = specs.length; 26 | for (var i=0; i < num; i++) { 27 | el = "#vis-" + i; 28 | jsonVis = YAML.parse(specs[i].textContent); 29 | console.log(vl.compile(jsonVis).spec == undefined) 30 | htmlString = "
" 31 | specs[i].insertAdjacentHTML('beforebegin', htmlString); 32 | specs[i].style.display = 'none'; 33 | vega.embed(el, jsonVis, opts); 34 | }; 35 | }; 36 | 37 | //Convert from Markdown to HTML 38 | var input = editor.getValue(); 39 | var output = document.getElementById("visdown-output"); 40 | 41 | visdown = function () { 42 | console.log('visdown'); 43 | var markdownText = editor.getValue(); 44 | output.innerHTML = marked(markdownText) 45 | // IncrementalDOM.patch( 46 | // output, 47 | // md.renderToIncrementalDOM(markdownText) 48 | // ); 49 | vegaliteRender(); 50 | } 51 | 52 | visdown() 53 | 54 | var waiting; 55 | editor.on("change", function() { 56 | visdown(); 57 | }); 58 | 59 | function viewSource(source) { 60 | var header = '' + " " + '' + '
';
61 | 		var footer = '
' + " " + ''; 62 | var doc = header + source + footer; 63 | var win = window.open(''); 64 | //win.document.write(header + source + footer); 65 | //win.document.title = 'Vega JSON Source'; 66 | return doc; 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /static/css/visdown.css: -------------------------------------------------------------------------------- 1 | html { 2 | overflow: hidden; 3 | height: 100% 4 | } 5 | 6 | body { 7 | margin: 0; 8 | padding: 0; 9 | height: 100%; 10 | overflow-y: scroll; 11 | overflow-x: hidden; 12 | font-family: 'PT Sans', sans-serif; 13 | font-size: 16px; 14 | line-height: 1.4rem; 15 | text-rendering: optimizeLegibility; 16 | transition: all 700ms; 17 | } 18 | 19 | h1, h2, h3, h4, h5 { 20 | font-family: 'PT Serif', sans-serif; 21 | } 22 | 23 | h1 { 24 | font-size: 2rem;} 25 | h2 { 26 | font-size: 1.6rem;} 27 | 28 | .yin { 29 | color: #111; 30 | background-color: #FDFDFD; 31 | } 32 | 33 | .yang { 34 | color: #FDFDFD; 35 | background-color: #111; 36 | } 37 | 38 | header { 39 | width: 3.5rem; 40 | position: absolute; 41 | top: 0; 42 | bottom: 0; 43 | /* border-right: 1px solid lightgrey; */ 44 | } 45 | 46 | nav { 47 | margin-top: 5rem; 48 | } 49 | 50 | .logo { 51 | display: block; 52 | position: absolute; 53 | width: 3.5rem; 54 | height: 3.5rem; 55 | margin: 0 auto; 56 | } 57 | 58 | .icon { 59 | display: block; 60 | width: 1.6rem; 61 | height: 1.6rem; 62 | margin: 1.2rem auto; 63 | cursor: pointer; 64 | } 65 | 66 | .icons-bottom { 67 | width: 3.5rem; 68 | position: absolute; 69 | bottom: 0; 70 | } 71 | 72 | #editor { 73 | padding: 0; 74 | margin: 0 0 0 3.5rem; 75 | } 76 | 77 | .CodeMirror { 78 | font-family: "Menlo", monospace; 79 | height: 100%; 80 | max-width: 52em; 81 | margin: 0 auto; 82 | vertical-align: top; 83 | box-sizing: border-box; 84 | padding: 20px 20px 0 20px; 85 | background-color: #FDFDFD; 86 | transition: all 700ms; 87 | } 88 | 89 | #output { 90 | display: none; 91 | height: 100%; 92 | max-width: 46em; 93 | margin: 0 auto; 94 | vertical-align: top; 95 | box-sizing: border-box; 96 | padding: 60px 20px 0 20px; 97 | } 98 | 99 | .cm-header { 100 | font-weight: 800; 101 | } 102 | .cm-header-1 { font-size: 150%; } 103 | .cm-header-2 { font-size: 130%; } 104 | .cm-header-3 { font-size: 120%; } 105 | .cm-header-4 { font-size: 110%; } 106 | .cm-header-5 { font-size: 100%; } 107 | .cm-header-6 { font-size: 90%; } 108 | 109 | /* .markdown-body pre { 110 | background-color: white; 111 | } 112 | 113 | code { 114 | color: #f66; 115 | } 116 | 117 | table { 118 | border-spacing: 0.7rem; 119 | } 120 | 121 | h1 {font-size: 2rem;} 122 | h2 {font-size: 1.6rem;} 123 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Visdown - Markdown for Visualisation 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 47 |
48 | 49 |
50 |
51 | 52 |
53 |
54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /pages/visual-layer.md: -------------------------------------------------------------------------------- 1 | # Visual Layer 2 | 3 | - Marks: Points, Ticks, Lines, Bar, Area, Glyphs, Polygon, ... 4 | - Channels: Position, Size, Color, Shape, Path, ... 5 | - Position: Identity, Stacked, Jitter, Dodge, ... 6 | - Scale: Linear, Log, ... 7 | - Coordinate: Cartesian, Polar, Geo, Parallel 8 | - Layout: Single, Facetting, Multi-Chart 9 | 10 | 11 | ## Marks 12 | 13 | Marks are the basic shapes used to represent the data. Play around and see if you change the `mark` to `point`, `circle`, `square`, `text`, `tick`, `bar`, `line`, and `area`. 14 | 15 | 16 | ```vis 17 | data: 18 | url: "data/notes.csv" 19 | mark: line 20 | encoding: 21 | x: 22 | type: temporal 23 | field: year 24 | y: 25 | type: quantitative 26 | field: money 27 | color: 28 | type: nominal 29 | field: denom 30 | ``` 31 | 32 | ## Channels 33 | 34 | These properties are used to set the position and appearance of the mark 35 | 36 | - Position x 37 | - Position y 38 | - Color 39 | - Shape 40 | - Size 41 | 42 | 43 | Change the `fields` in `x` ,`y`, `shape`, `size` and `color` 44 | 45 | ```vis 46 | data: 47 | url: "data/notes.csv" 48 | transform: 49 | - 50 | filter: datum.year > 2010 51 | mark: circle 52 | encoding: 53 | x: 54 | type: quantitative 55 | field: money 56 | y: 57 | type: quantitative 58 | field: number 59 | color: 60 | type: nominal 61 | field: denom 62 | size: 63 | type: quantitative 64 | field: value 65 | ``` 66 | 67 | ## Position 68 | 69 | - Identity 70 | - Stacked 71 | - Normalise 72 | - Jitter 73 | 74 | To stack the values, we can use `aggregate` as `sum` 75 | 76 | ```vis 77 | data: 78 | url: "data/notes.csv" 79 | mark: area 80 | encoding: 81 | x: 82 | type: temporal 83 | field: year 84 | y: 85 | type: quantitative 86 | field: money 87 | aggregate: sum 88 | color: 89 | type: nominal 90 | field: denom 91 | ``` 92 | 93 | To normalize the values, we can use `config` to make the `stacked` as `normalize` 94 | 95 | ```vis 96 | data: 97 | url: "data/notes.csv" 98 | mark: area 99 | encoding: 100 | x: 101 | type: temporal 102 | field: year 103 | y: 104 | type: quantitative 105 | field: money 106 | aggregate: sum 107 | color: 108 | type: nominal 109 | field: denom 110 | config: 111 | mark: 112 | stacked: normalize 113 | ``` 114 | 115 | ## Facet 116 | 117 | We can also create small multiple charts using `row` or `column` encoding 118 | 119 | - Row wise 120 | - Column wise 121 | 122 | ```vis 123 | data: 124 | url: "data/notes.csv" 125 | transform: 126 | - 127 | filter: datum.denom > 50 128 | mark: area 129 | encoding: 130 | x: 131 | type: temporal 132 | field: year 133 | y: 134 | type: quantitative 135 | field: money 136 | color: 137 | type: nominal 138 | field: denom 139 | column: 140 | type: nominal 141 | field: denom 142 | ``` 143 | -------------------------------------------------------------------------------- /experiments/datum.js: -------------------------------------------------------------------------------- 1 | /* 2 | * datum - a shorthand for vega-lite 3 | * Copyright (c) 2017, Amit Kapoor. (MIT Licensed) 4 | * https://github.com/amitkaps/visdown 5 | */ 6 | 7 | ;(function() { 8 | 9 | // Create TOKENS by removing | or \n from raw spec 10 | function tokenizer(visCode) { 11 | let tokens = visCode.trim() 12 | .split(/[|\n]+/) 13 | .map(str => str.trim()); 14 | return tokens; 15 | } 16 | 17 | // Create GRAMMAR FUNCTIONS 18 | function _data(type, exp) { 19 | let data = {"data": {"url": exp}}; 20 | return data; 21 | } 22 | 23 | function _transform(type, exp) { 24 | let transform = {"transform": [{"filter": exp}]}; 25 | return transform; 26 | } 27 | 28 | function _mark(type, exp) { 29 | let encode = _encoding(exp); 30 | let mark_encoding = {"mark": type, "encoding": encode} 31 | return mark_encoding 32 | } 33 | 34 | function _encoding(exp) { 35 | let etokens = exp.split(",").map(str => str.trim()) 36 | let encode = {} 37 | for(let i = 0; i < etokens.length; i++){ 38 | let etoken = etokens[i].split("=").map(str => str.trim()); 39 | console.log(etoken) 40 | let posChannel = etoken[0]; 41 | let fieldType = etoken[1].split(":").map(str => str.trim()); 42 | let field = fieldType[0], type = fieldType[1], aggregate = fieldType[2] 43 | encode[posChannel] = {"field": field, "type": type, "aggregate": aggregate} 44 | } 45 | return encode; 46 | } 47 | 48 | // Set up TYPE to GRAMMAR FUNCTION mapping 49 | const grammarFunc = { 50 | "data" : _data, 51 | "filter": _transform, "bin": "_transform", 52 | "point" : _mark, "area" : _mark, "line": _mark, 53 | "bar" : _mark, "circle": _mark, 54 | "rect" : _mark, "line" : _mark, 55 | "single": "_selection", "multi": "_selection", "interval": "_selection" 56 | } 57 | 58 | // Use LEXER to create SEMANTIC of 'type' and 'grammar' from tokens 59 | function lexer(tokens) { 60 | let lex = []; 61 | for (let i = 0; i < tokens.length; i++) { 62 | let token = tokens[i].split("("); 63 | let type = token[0].trim(); 64 | let exp = token[1].split(")")[0].trim(); 65 | let grammar = grammarFunc[type](type, exp); 66 | lex[i] = {"type": type, "exp": exp, "grammar": grammar}; 67 | } 68 | return lex; 69 | } 70 | 71 | function merge(obj) { 72 | let target, key; 73 | for (let i = 0; i < arguments.length; i++) { 74 | target = arguments[i]; 75 | for (key in target) { 76 | if (Object.prototype.hasOwnProperty.call(target, key)) { 77 | obj[key] = target[key]; 78 | } 79 | } 80 | } 81 | return obj; 82 | } 83 | 84 | // Use PARSER to generate the Vega-Lite spec 85 | function parser(lex) { 86 | let spec = {} ; 87 | for (let i = 0; i < lex.length; i++) { 88 | let type = lex[i].type; 89 | let grammar = lex[i].grammar; 90 | spec = merge(spec, grammar); 91 | } 92 | return spec; 93 | } 94 | 95 | // Create vlSpec from the visCode 96 | function datum(visCode) { 97 | let tokens = tokenizer(visCode); 98 | let lex = lexer(tokens); 99 | console.log(lex); 100 | let spec = parser(lex); 101 | console.log(spec) 102 | return spec; 103 | } 104 | 105 | 106 | 107 | if (typeof module !== 'undefined' && typeof exports === 'object') { 108 | module.exports = datum; 109 | } else if (typeof define === 'function' && define.amd) { 110 | define(function() { return datum; }); 111 | } else { 112 | this.datum = datum; 113 | } 114 | 115 | }).call(function() { 116 | return this || (typeof window !== 'undefined' ? window : global); 117 | }()); -------------------------------------------------------------------------------- /pages/composition.md: -------------------------------------------------------------------------------- 1 | # Composition 2 | 3 | - Single View 4 | - Multiple View 5 | - Layering 6 | - Concatentation 7 | - Facetting 8 | - Repeat 9 | 10 | ## Single View - 1 11 | 12 | ```vis 13 | data: 14 | url: data/notes.csv 15 | transform: 16 | - filter: datum.year == 2015 17 | mark: bar 18 | encoding: 19 | y: 20 | type: nominal 21 | field: denom 22 | x: 23 | type: quantitative 24 | field: number 25 | color: 26 | type: nominal 27 | field: denom 28 | size: 29 | value: 3 30 | ``` 31 | 32 | ## Single View - 2 33 | 34 | 35 | ```vis 36 | data: 37 | url: data/notes.csv 38 | transform: 39 | - filter: datum.year == 2015 40 | mark: circle 41 | encoding: 42 | y: 43 | type: nominal 44 | field: denom 45 | x: 46 | type: quantitative 47 | field: number 48 | color: 49 | type: nominal 50 | field: denom 51 | size: 52 | value: 100 53 | 54 | ``` 55 | 56 | ## Layered View 57 | 58 | Simple Example 59 | 60 | ```vis 61 | data: 62 | url: data/notes.csv 63 | transform: 64 | - filter: datum.year == 2015 65 | layer: 66 | - mark: bar 67 | encoding: 68 | y: 69 | type: nominal 70 | field: denom 71 | x: 72 | type: quantitative 73 | field: number 74 | color: 75 | type: nominal 76 | field: denom 77 | size: 78 | value: 2 79 | - mark: circle 80 | encoding: 81 | y: 82 | type: nominal 83 | field: denom 84 | x: 85 | type: quantitative 86 | field: number 87 | color: 88 | type: nominal 89 | field: denom 90 | size: 91 | value: 100 92 | 93 | ``` 94 | 95 | ## Concat 96 | 97 | 98 | ```vis 99 | hconcat: 100 | - data: 101 | url: data/notes.csv 102 | transform: 103 | - filter: datum.year == 2015 104 | mark: bar 105 | encoding: 106 | x: 107 | type: nominal 108 | field: denom 109 | y: 110 | type: quantitative 111 | field: number 112 | color: 113 | type: nominal 114 | field: denom 115 | - data: 116 | url: data/notes.csv 117 | transform: 118 | - filter: datum.year == 2015 119 | mark: circle 120 | encoding: 121 | x: 122 | type: nominal 123 | field: denom 124 | y: 125 | type: quantitative 126 | field: number 127 | color: 128 | type: nominal 129 | field: denom 130 | size: 131 | value: 100 132 | 133 | ``` 134 | 135 | ## Facet 136 | 137 | ```vis 138 | data: 139 | url: data/notes.csv 140 | transform: 141 | - filter: datum.year > 2013 142 | mark: bar 143 | encoding: 144 | x: 145 | type: nominal 146 | field: denom 147 | y: 148 | type: quantitative 149 | field: number 150 | color: 151 | type: nominal 152 | field: denom 153 | column: 154 | type: nominal 155 | field: year 156 | ``` 157 | 158 | 159 | ## Repeat 160 | 161 | ```vis 162 | data: 163 | url: data/notes.csv 164 | transform: 165 | - filter: datum.year == 2015 166 | repeat: 167 | column: 168 | - money 169 | - number 170 | spec: 171 | mark: bar 172 | encoding: 173 | x: 174 | type: nominal 175 | field: denom 176 | y: 177 | type: quantitative 178 | field: 179 | repeat: column 180 | color: 181 | type: nominal 182 | field: denom 183 | config: 184 | axis: 185 | orient: bottom 186 | ``` 187 | 188 | ## Resolve 189 | 190 | e.g. layering charts with different scales 191 | 192 | **First Layer** 193 | 194 | ```vis 195 | width: 400 196 | height: 300 197 | data: 198 | url: data/notes.csv 199 | mark: area 200 | encoding: 201 | x: 202 | field: year 203 | type: temporal 204 | axis: 205 | format: %Y 206 | labelAngle: 0 207 | y: 208 | aggregate: sum 209 | field: money 210 | type: quantitative 211 | stack: normalize 212 | axis: 213 | format: % 214 | color: 215 | field: denom 216 | type: nominal 217 | ``` 218 | 219 | **Second Layer** 220 | 221 | ```vis 222 | width: 400 223 | height: 300 224 | data: 225 | url: data/notes.csv 226 | mark: line 227 | encoding: 228 | x: 229 | field: year 230 | type: temporal 231 | axis: 232 | format: %Y 233 | labelAngle: 0 234 | y: 235 | aggregate: sum 236 | field: number 237 | type: quantitative 238 | size: 239 | value: 3 240 | color: 241 | value: black 242 | 243 | ``` 244 | 245 | **Combined** 246 | 247 | ```vis 248 | width: 400 249 | height: 300 250 | data: 251 | url: data/notes.csv 252 | layer: 253 | - mark: area 254 | encoding: 255 | x: 256 | field: year 257 | type: temporal 258 | axis: 259 | format: %Y 260 | labelAngle: 0 261 | y: 262 | aggregate: sum 263 | field: money 264 | type: quantitative 265 | stack: normalize 266 | axis: 267 | format: % 268 | color: 269 | field: denom 270 | type: nominal 271 | - mark: line 272 | encoding: 273 | x: 274 | field: year 275 | type: temporal 276 | axis: 277 | format: %Y 278 | labelAngle: 0 279 | y: 280 | aggregate: sum 281 | field: number 282 | type: quantitative 283 | size: 284 | value: 3 285 | color: 286 | value: black 287 | resolve: 288 | y: 289 | scale: independent 290 | ``` 291 | -------------------------------------------------------------------------------- /pages/data.md: -------------------------------------------------------------------------------- 1 | # Datasets 2 | 3 | You can use external datasets or use the following datasets to try out Visdown. 4 | 5 | ## Loading data 6 | You can use any csv, tsv or json file to load your data set. 7 | 8 | ``` 9 | data: 10 | 11 | ## Sample 12 | 13 | This the most simple dataset available. 14 | 15 | | area | sales | profit |  16 | |:--------|-------:|-------:| 17 | | North   |  5  |    2 |   18 | | East    |  25  |    8 |   19 | | West    |  15  |    6 |   20 | | South   |  20  |    5 |   21 | | Central |  10  |    3 |   22 | 23 | Metadata 24 | - Filename: `sample.csv` 25 | - Observations `(n)` : 5 26 | - Dimensions `(p)` : 3 27 | 28 | ```vis 29 | data: 30 | - url: sample.csv 31 | mark: point 32 | encoding: 33 | x: 34 | (data/sample.csv) | point(x=sales:Q, y=profit:Q, color=area:N) 35 | ``` 36 | 37 | ## Cars 38 | 39 | A list of Indian cars and basic stats 40 | 41 | | brand | model  |  price |  kmpl | type |   bhp | 42 | |:--------|:-------|-------:|-------:|:----------|-------:| 43 | | Tata    | Nano   |    199 |   23.9 | Hatchback |    38 | 44 | | Suzuki | Alto800|   248 |   22.7 | Hatchback |    47 | 45 | | Hyundai | EON    |    302 |   21.1 | Hatchback |    55 | 46 | | Nissan | Datsun |    312 |   20.6 | Hatchback |    67 | 47 | | ...     | ...    |   ... |    ... | ...       |   ... | 48 | | Suzuki  | Ciaz   |   725 | 20.7 | Sedan     |    91 | 49 | | Skoda   | Rapid  |   756 |   15.0 | Sedan     |   104 | 50 | | Hyundai | Verna  |   774 |   17.4 | Sedan     |   106 | 51 | | VW      | Vento  |    785 |   16.1 | Sedan     |   104 | 52 | 53 | Metadata 54 | - Filename: `cars.csv` 55 | - Observations `(n)`: 42 56 | - Dimensions `(p)` : 6 57 | - `brand`: brand 58 | - `model`: model name 59 | - `price`: price in '000 INR 60 | - `kmpl` : efficiency of the car in km per liter 61 | - `type` : type either Hatchback or Sedan 62 | - `bhp` : brake horsepower 63 | - Source: Adapted from a car comparison website 64 | 65 | ```vis 66 | data(data/cars.csv) | point(x=kmpl:Q, y = price:Q) 67 | ``` 68 | 69 | ## Flights 70 | 71 | This dataset was is about flight punctuality from 5 London Airport to 5 major US airports 72 | 73 | | source| dest | airline | flights| onTimePerf| delayAvg | year | 74 | |:------|:-----|:--------|-------:|----------:|---------:|-----:| 75 | | LHR   | ORD |  AA | 2490 |    63.33 | 21.11 | 2010 | 76 | | LHR | ORD |  BA | 1413 |   57.36 | 23.30 | 2010 | 77 | | LHR | ORD |  UA  | 2105 |   73.24 | 14.57 | 2010 | 78 | | LHR | ORD |  VS | 218 |   77.06 | 11.10 | 2010 | 79 | | ...   | ...  |  ...  | ... |  ...  |  ... | ... | 80 | | LHR | IAD |  US | 2134 |   82.05 | 13.24 | 2016 | 81 | | LHR | IAD |  VS | 699 |   84.69 | 8.02 | 2016 | 82 | | LCY | JFK |  BA | 921 |   90.01 | 5.26 | 2016 | 83 | | LTN | EWR |  DJT | 333 |   87.05 | 8.44 | 2016 | 84 | 85 | Metadata 86 | - Filename: `flights.csv` 87 | - Observations `(n)`: 157 88 | - Dimensions `(p)` : 7 89 | - `source` : The source IATA airport code 90 | - `dest` : The destination IATA airport code 91 | - `airline` : The two letter IATA code for the airline 92 | - `flights` : The number of flights in that year 93 | - `onTimePerf` : The precentage of flights on-time in that route 94 | - `delayAvg`: The average delay in minutes for that route and airline 95 | - `year` : The year of data 96 | - Source: Adapted from flight punctuality statistics from the London Civil Aviation Authority 97 | 98 | ```vis 99 | data(london.csv) 100 | filter(datum.year == 2016) 101 | rect(x=source:N, y=dest:N, color=sum(flights):Q) 102 | ``` 103 | 104 | ## Notes 105 | 106 | This dataset was inspired by the demonetisation of INR 500 and INR 1000 notes in India conducted in 2016. 107 | 108 | | year | type   |  denom |  value | money | number | 109 | |--------:|:-------|-------:|-------:|--------:|-------:| 110 | | 1977    | Notes  |   0001 |    1 | 2.72 |  2.720 | 111 | | 1977 | Notes |   1000 |   1000 | 0.55 |  0.001 | 112 | | 1977 | Notes  |   0002 |   2 | 1.48 |  0.740 | 113 | | 1977 | Notes  |   0050 |   50 | 9.95 |  0.199 | 114 | | ...     | ...    |   ... |    ... |  ... |    ... | 115 | | 2015    | Notes  |   0500 |    500 | 7853.75 | 15.708 | 116 | | 2015 | Notes |   0001 |   1 | 3.09 |  3.090 | 117 | | 2015 | Notes  |   0010 |   10 | 320.15 | 32.015 | 118 | | 2015 | Notes  |   1000 |   1000 | 6325.68 |  6.326 | 119 | 120 | Metadata 121 | - Filename: `notes.csv` 122 | - Observations `(n)`: 351 123 | - Features `(p)` : 6 124 | - `year` : The year of circulation 125 | - `type` : The type of currency 126 | - `denom` : The denomination of the currency 127 | - `value` : The face value of the currency 128 | - `money` : The monetary value of currency in circulation (in INR Billion) 129 | - `number`: The number of currency in circulation (in INR Billion) 130 | - Source: It is taken from Reserve Bank of India’s - Handbook of Statistics on Indian Economy 2016. Within it, Table 160 deals with [Notes and Coins in Circulation](https://www.rbi.org.in/scripts/PublicationsView.aspx?id=17293) and this dataset is only about the Notes circulation. 131 | 132 | ```vis 133 | data(data/notes.csv) 134 | filter(datum.year == 2015) 135 | bar(x=denom:N, y=money:Q, color=denom:N) 136 | ``` 137 | 138 | 139 | -------------------------------------------------------------------------------- /pages/interact-layer.md: -------------------------------------------------------------------------------- 1 | # Interaction Layer 2 | 3 | - *Selection*: Discrete (single, multi), Continuous (interval), Voronoi (nearest), Remove (toggle) 4 | - *Events*: `click`, `dblclick`, `mouseover`, `drag`,... 5 | - *Condition*: Change encoding, scale, filter, ... 6 | - *Bind*: Input elements (range, radio-box,...) 7 | - *Project*: default, fields 8 | - *Translate*: scale 9 | 10 | 11 | **Interaction Patterns** 12 | 13 | - **Select**: mark something as interesting e.g. *Highlighting* 14 | - **Explore**: show me something else e.g. *Pan or Zoom* 15 | - **Encode**: show me a different representation e.g. *change Color, Position* 16 | - **Abstract/Elaborate**: show me more or less detail e.g. *Overview & Details* 17 | - **Filter**: show me something conditionally e.g. *Dynamic Queries*, *Cross Filter* 18 | - **Connect**: show me related items e.g. *Brushing & Linking* 19 | - **Reconfigure**: show me a different arrangement e.g. *Sorting*, *Indexing* 20 | - **Transition**: move between different views e.g. *Staging & Animation* 21 | 22 | 23 | ## Select: **Highlighting** 24 | 25 | **Single** 26 | 27 | Select single value using `click` 28 | 29 | ```vis 30 | data: 31 | url: data/notes.csv 32 | transform: 33 | - filter: datum.year == 2015 34 | selection: 35 | pts: 36 | type: single 37 | mark: circle 38 | encoding: 39 | x: 40 | type: nominal 41 | field: denom 42 | y: 43 | type: quantitative 44 | field: number 45 | color: 46 | condition: 47 | selection: pts 48 | type: nominal 49 | field: denom 50 | value: grey 51 | size: 52 | value: 250 53 | ``` 54 | 55 | **Multiple** 56 | 57 | Select multiple value using `click` & `shift` + `click` 58 | 59 | ```vis 60 | data: 61 | url: data/notes.csv 62 | transform: 63 | - filter: datum.year == 2015 64 | selection: 65 | pts: 66 | type: multi 67 | mark: circle 68 | encoding: 69 | x: 70 | type: nominal 71 | field: denom 72 | y: 73 | type: quantitative 74 | field: number 75 | color: 76 | condition: 77 | selection: pts 78 | type: nominal 79 | field: denom 80 | value: grey 81 | size: 82 | value: 250 83 | ``` 84 | 85 | ## Brushing 86 | 87 | **Interval / Brushing** 88 | 89 | Select an interval by dragging the mouse 90 | 91 | ```vis 92 | data: 93 | url: data/notes.csv 94 | transform: 95 | - filter: datum.year == 2015 96 | selection: 97 | pts: 98 | type: interval 99 | mark: circle 100 | encoding: 101 | x: 102 | type: nominal 103 | field: denom 104 | y: 105 | type: quantitative 106 | field: number 107 | color: 108 | condition: 109 | selection: pts 110 | type: nominal 111 | field: denom 112 | value: grey 113 | size: 114 | value: 250 115 | ``` 116 | 117 | ## Highlighting 118 | 119 | **Direct** 120 | 121 | Select direct value using `hover` 122 | 123 | ```vis 124 | data: 125 | url: data/cars.csv 126 | selection: 127 | pts: 128 | type: single 129 | on: mouseover 130 | mark: circle 131 | encoding: 132 | x: 133 | type: quantitative 134 | field: kmpl 135 | scale: 136 | domain: [12,25] 137 | y: 138 | type: quantitative 139 | field: price 140 | scale: 141 | domain: [100,900] 142 | color: 143 | condition: 144 | selection: pts 145 | field: type 146 | type: nominal 147 | value: grey 148 | size: 149 | value: 200 150 | width: 450 151 | height: 300 152 | ``` 153 | 154 | **Nearest** 155 | 156 | Select nearest value using `hover` 157 | 158 | 159 | ```vis 160 | data: 161 | url: data/cars.csv 162 | selection: 163 | pts: 164 | type: single 165 | on: mouseover 166 | nearest: true 167 | mark: circle 168 | encoding: 169 | x: 170 | type: quantitative 171 | field: kmpl 172 | scale: 173 | domain: [12,25] 174 | y: 175 | type: quantitative 176 | field: price 177 | scale: 178 | domain: [100,900] 179 | color: 180 | condition: 181 | selection: pts 182 | field: type 183 | type: nominal 184 | value: grey 185 | size: 186 | value: 200 187 | width: 450 188 | height: 300 189 | ``` 190 | 191 | **Multi Line Highlight** 192 | 193 | ```vis 194 | width: 500 195 | height: 300 196 | data: 197 | url: data/notes.csv 198 | config: 199 | point: 200 | opacity: 0 201 | layer: 202 | - selection: 203 | highlight: 204 | type: single 205 | 'on': mouseover 206 | nearest: 'true' 207 | fields: 208 | - denom 209 | mark: point 210 | encoding: 211 | x: 212 | field: year 213 | type: temporal 214 | axis: 215 | format: "%Y" 216 | labelAngle: 0 217 | y: 218 | field: number 219 | type: quantitative 220 | color: 221 | field: denom 222 | type: nominal 223 | - mark: line 224 | encoding: 225 | x: 226 | field: year 227 | type: temporal 228 | axis: 229 | y: 230 | field: number 231 | type: quantitative 232 | color: 233 | field: denom 234 | type: nominal 235 | size: 236 | condition: 237 | selection: 238 | not: highlight 239 | value: 1 240 | value: 3 241 | ``` 242 | 243 | 244 | 245 | ## Dynamic Queries: Input Binding 246 | 247 | Two-way binding between Input Types and Selection 248 | 249 | ```vis 250 | data: 251 | url: data/cars.csv 252 | selection: 253 | pts: 254 | type: single 255 | fields: 256 | - type 257 | bind: 258 | input: select 259 | options: 260 | - Hatchback 261 | - Sedan 262 | mark: circle 263 | encoding: 264 | x: 265 | type: quantitative 266 | field: kmpl 267 | scale: 268 | domain: [12,25] 269 | y: 270 | type: quantitative 271 | field: price 272 | scale: 273 | domain: [100,900] 274 | color: 275 | condition: 276 | selection: pts 277 | field: type 278 | type: nominal 279 | value: grey 280 | size: 281 | value: 200 282 | width: 450 283 | height: 300 284 | ``` 285 | -------------------------------------------------------------------------------- /data/flights.csv: -------------------------------------------------------------------------------- 1 | "source","dest","airline","flights","onTimePerf","delayAvg","year" 2 | "LHR","ORD","AA",2490,66.33,21.11,2010 3 | "LHR","ORD","BA",1413,57.63,23.3,2010 4 | "LHR","ORD","UA",2105,73.24,14.57,2010 5 | "LHR","ORD","VS",218,77.06,11.1,2010 6 | "LHR","LAX","AA",706,66.38,17.66,2010 7 | "LHR","LAX","BA",1914,50.18,31.01,2010 8 | "LHR","LAX","UA",698,81.81,13.62,2010 9 | "LHR","LAX","VS",1285,56.86,21.92,2010 10 | "LHR","JFK","AA",3205,67.36,20.31,2010 11 | "LHR","JFK","BA",4181,66.59,20.84,2010 12 | "LHR","JFK","DL",1611,62.12,23.74,2010 13 | "LHR","JFK","KU",305,46.56,38.75,2010 14 | "LHR","JFK","VS",2067,59.62,23.69,2010 15 | "LHR","EWR","BA",1828,70.25,17.67,2010 16 | "LHR","EWR","CO",2697,69.28,18.87,2010 17 | "LHR","EWR","VS",1399,65.62,23.15,2010 18 | "LHR","IAD","BA",2011,62.11,21.71,2010 19 | "LHR","IAD","UA",2094,74.67,14.11,2010 20 | "LHR","IAD","VS",700,66.24,19.75,2010 21 | "LCY","JFK","BA",1012,89.12,5.67,2010 22 | "LHR","ORD","AA",2532,76.87,13.34,2011 23 | "LHR","ORD","BA",1440,76.32,14.42,2011 24 | "LHR","ORD","UA",2106,79.36,15.2,2011 25 | "LHR","ORD","VS",302,82.72,8.66,2011 26 | "LHR","LAX","AA",730,75.48,13.66,2011 27 | "LHR","LAX","BA",1984,63.46,18.47,2011 28 | "LHR","LAX","UA",698,83.52,11.7,2011 29 | "LHR","LAX","VS",1397,79,11.2,2011 30 | "LHR","JFK","AA",2917,75.8,14.77,2011 31 | "LHR","JFK","BA",4944,73.56,14.65,2011 32 | "LHR","JFK","DL",2144,80.91,13.05,2011 33 | "LHR","JFK","KU",302,52.65,30.02,2011 34 | "LHR","JFK","VS",2104,76.32,15.09,2011 35 | "LHR","EWR","BA",2129,80.7,11.24,2011 36 | "LHR","EWR","CO",3503,78.42,14.19,2011 37 | "LHR","EWR","VS",1410,77.52,13.39,2011 38 | "LHR","IAD","BA",2157,74.08,14.11,2011 39 | "LHR","IAD","UA",2516,80.79,14,2011 40 | "LHR","IAD","VS",711,82.42,9.73,2011 41 | "LCY","JFK","BA",1031,92.05,4.12,2011 42 | "LHR","ORD","AA",2523,72.07,20.03,2012 43 | "LHR","ORD","BA",1445,70.03,17.73,2012 44 | "LHR","ORD","UA",2102,76.08,15.35,2012 45 | "LHR","ORD","VS",308,83.77,8.31,2012 46 | "LHR","LAX","AA",714,75.35,12.03,2012 47 | "LHR","LAX","BA",1874,63.48,18.34,2012 48 | "LHR","LAX","UA",693,76.16,14.88,2012 49 | "LHR","LAX","VS",1324,76.13,14.08,2012 50 | "LHR","JFK","AA",3367,75.72,12.75,2012 51 | "LHR","JFK","BA",5129,69.28,17.68,2012 52 | "LHR","JFK","DL",2151,77.63,13.59,2012 53 | "LHR","JFK","KU",307,52.12,32.02,2012 54 | "LHR","JFK","VS",2227,81.9,11.32,2012 55 | "LHR","EWR","BA",1920,73.02,15.88,2012 56 | "LHR","EWR","CO",612,84.48,9.24,2012 57 | "LHR","EWR","UA",2872,69.76,17.91,2012 58 | "LHR","EWR","VS",1421,76.14,16.68,2012 59 | "LHR","IAD","BA",2014,71.45,16.23,2012 60 | "LHR","IAD","UA",2444,69.04,18.98,2012 61 | "LHR","IAD","VS",703,87.06,7.71,2012 62 | "LCY","JFK","BA",474,91.33,3.74,2012 63 | "LCY","JFK","BA",537,89.37,4.71,2012 64 | "LHR","ORD","AA",2513,74.69,15.29,2013 65 | "LHR","ORD","BA",1440,65.35,20.84,2013 66 | "LHR","ORD","UA",2110,78.39,14.13,2013 67 | "LHR","ORD","VS",324,83.02,9.05,2013 68 | "LHR","LAX","AA",728,76.48,12.56,2013 69 | "LHR","LAX","BA",1864,59.5,27.43,2013 70 | "LHR","LAX","UA",702,85.47,9.86,2013 71 | "LHR","LAX","VS",1288,79,13.76,2013 72 | "LHR","JFK","AA",2991,76.4,13.73,2013 73 | "LHR","JFK","BA",5350,66.97,18.95,2013 74 | "LHR","JFK","DL",2166,82.09,10.81,2013 75 | "LHR","JFK","KU",306,62.42,21.53,2013 76 | "LHR","JFK","VS",2825,81.91,10.53,2013 77 | "LHR","EWR","BA",1838,71.44,16.72,2013 78 | "LHR","EWR","UA",3494,80.59,12.36,2013 79 | "LHR","EWR","VS",1419,81.66,11.7,2013 80 | "LHR","IAD","BA",2012,71.02,18.67,2013 81 | "LHR","IAD","UA",2496,80.39,12.82,2013 82 | "LHR","IAD","VS",702,86.89,7.1,2013 83 | "LCY","JFK","BA",945,90.64,4.58,2013 84 | "LGW","LAX","DY",105,72.38,36.83,2014 85 | "LGW","JFK","DY",156,51.92,27.79,2014 86 | "LHR","ORD","AA",2476,73.5,22.09,2014 87 | "LHR","ORD","BA",1444,65.28,18.7,2014 88 | "LHR","ORD","UA",2110,77.56,13.68,2014 89 | "LHR","ORD","VS",348,81.32,8.86,2014 90 | "LHR","LAX","AA",728,76.79,18.56,2014 91 | "LHR","LAX","BA",1450,56.84,23.1,2014 92 | "LHR","LAX","DL",127,92.13,6.92,2014 93 | "LHR","LAX","UA",698,85.1,8.53,2014 94 | "LHR","LAX","VS",1217,80.99,12.58,2014 95 | "LHR","JFK","AA",2287,78.18,14.74,2014 96 | "LHR","JFK","BA",6018,71.29,16.59,2014 97 | "LHR","JFK","DL",2123,82.13,11.19,2014 98 | "LHR","JFK","KU",310,48.22,33.17,2014 99 | "LHR","JFK","VS",2820,79.77,12.45,2014 100 | "LHR","EWR","BA",1943,71.46,19.7,2014 101 | "LHR","EWR","UA",3485,78.3,15.19,2014 102 | "LHR","EWR","VS",1420,86.6,8.37,2014 103 | "LHR","IAD","BA",1807,74.58,15.31,2014 104 | "LHR","IAD","UA",2130,81.13,13.61,2014 105 | "LHR","IAD","VS",695,89.06,6.9,2014 106 | "LCY","JFK","BA",1003,91.23,4.43,2014 107 | "LGW","LAX","DY",328,66.46,21.41,2015 108 | "LGW","JFK","DY",543,64.09,31.78,2015 109 | "LHR","ORD","AA",2062,72.09,27.59,2015 110 | "LHR","ORD","BA",1442,71.4,16.24,2015 111 | "LHR","ORD","UA",2099,83.94,10.37,2015 112 | "LHR","ORD","VS",330,78.79,11.61,2015 113 | "LHR","LAX","AA",1265,75.42,14.5,2015 114 | "LHR","LAX","BA",1450,66.9,17.67,2015 115 | "LHR","LAX","DL",540,79.44,10.97,2015 116 | "LHR","LAX","UA",704,89.2,7.5,2015 117 | "LHR","LAX","VS",1230,80.81,12.74,2015 118 | "LHR","JFK","AA",2130,77.45,15.21,2015 119 | "LHR","JFK","BA",5994,77.84,13.61,2015 120 | "LHR","JFK","DL",2069,80.75,13.51,2015 121 | "LHR","JFK","KU",310,59.22,32.67,2015 122 | "LHR","JFK","VS",3363,76.35,13.82,2015 123 | "LHR","EWR","BA",1459,76.47,14.03,2015 124 | "LHR","EWR","DL",381,95.54,2.88,2015 125 | "LHR","EWR","UA",3493,79.23,16.31,2015 126 | "LHR","EWR","VS",871,81.75,10.7,2015 127 | "LHR","IAD","BA",1421,76.89,12.03,2015 128 | "LHR","IAD","UA",2126,81.74,14.02,2015 129 | "LHR","IAD","VS",703,85.49,12.59,2015 130 | "LCY","JFK","BA",937,92.74,4.52,2015 131 | "LTN","EWR","DJT",316,81.53,18.18,2015 132 | "LGW","LAX","DY",421,59.86,23.64,2016 133 | "LGW","LAX","DI",38,65.79,14.39,2016 134 | "LGW","JFK","BA",486,69.75,18.02,2016 135 | "LGW","JFK","DY",689,65.31,28.18,2016 136 | "LGW","JFK","DI",39,69.23,15.49,2016 137 | "LHR","ORD","AA",2453,71.82,26.15,2016 138 | "LHR","ORD","BA",1443,68.88,17.58,2016 139 | "LHR","ORD","UA",2085,82.25,14.2,2016 140 | "LHR","ORD","VS",333,89.79,5.07,2016 141 | "LHR","LAX","AA",1411,68.25,19.46,2016 142 | "LHR","LAX","BA",1452,54.34,24.89,2016 143 | "LHR","LAX","UA",700,87,8.48,2016 144 | "LHR","LAX","VS",1376,79.58,10.13,2016 145 | "LHR","JFK","AA",2623,76.82,21.41,2016 146 | "LHR","JFK","BA",5625,69.97,17.15,2016 147 | "LHR","JFK","DL",2081,80.37,13.42,2016 148 | "LHR","JFK","KU",253,19.76,71.96,2016 149 | "LHR","JFK","VS",3489,79.67,11.44,2016 150 | "LHR","EWR","AI",118,65.25,21.14,2016 151 | "LHR","EWR","BA",1444,76.11,13.49,2016 152 | "LHR","EWR","UA",3472,79.03,15.71,2016 153 | "LHR","EWR","VS",722,82.27,9.48,2016 154 | "LHR","IAD","BA",1415,71.59,17.44,2016 155 | "LHR","IAD","UA",2134,82.05,13.24,2016 156 | "LHR","IAD","VS",699,84.69,8.02,2016 157 | "LCY","JFK","BA",921,90.01,5.26,2016 158 | "LTN","EWR","DJT",333,87.05,8.44,2016 159 | -------------------------------------------------------------------------------- /js/editor.js: -------------------------------------------------------------------------------- 1 | // For Editor Operations 2 | // const visdown = window.visdown 3 | // const vega = window.vega 4 | // const vl = window.vl 5 | // const marked = window.marked 6 | // const YAML = window.yaml 7 | 8 | /** 9 | * Calculate a 32 bit FNV-1a hash 10 | * Found here: https://gist.github.com/vaiorabbit/5657561 11 | * Ref.: http://isthe.com/chongo/tech/comp/fnv/ 12 | * 13 | * @param {string} str the input value 14 | * @param {integer} [seed] optionally pass the hash of the previous chunk 15 | * @returns {string} 16 | */ 17 | function _hashFnv32a(str, seed) { 18 | /*jshint bitwise:false */ 19 | var i, l, hval = (seed === undefined) ? 0x811c9dc5 : seed; 20 | for (i = 0, l = str.length; i < l; i++) { 21 | hval ^= str.charCodeAt(i); 22 | hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); 23 | } 24 | // Convert to 8 digit hex string 25 | return ("0000000" + (hval >>> 0).toString(16)).substr(-8); 26 | } 27 | 28 | 29 | // Regex for getting vis code blocks and extracting viscode 30 | const re = /^((```)vis\s([\s\S]+?)(^\2)\s)/gm 31 | const newline = /\n/gm 32 | const visStart = /^```vis\s*\n/gm 33 | const visEnd = /^```\s*\n/gm 34 | 35 | function _countNewline(str){ 36 | if (str === "") {return 0 } else { 37 | let newlineMatch = str.match(newline) 38 | if (newlineMatch === null) {return 0} 39 | let len = newlineMatch.length 40 | return len 41 | } 42 | } 43 | 44 | function _getVisText(str){ 45 | let visText = str.split(visStart)[1].split(visEnd)[0] 46 | return visText 47 | } 48 | 49 | // Create Keys to work with CodeMirror Lines 50 | function _keys(str) { 51 | let visCode = str.match(re) || []; 52 | let nCount = str.match(newline); 53 | let keys = [] 54 | let checkString = str 55 | let start = 0 56 | visCode.forEach(function(code, i){ 57 | let visText = _getVisText(code); 58 | let spec = YAML.parse(visText) 59 | let hash = _hashFnv32a(visText.trim()); 60 | console.log(spec, code, hash); 61 | startIndex = checkString.indexOf(code) 62 | codeLength = code.length 63 | endIndex = startIndex + codeLength; 64 | beforeString = checkString.substring(0, startIndex+1); 65 | startLine = start + _countNewline(beforeString); 66 | codeLine = _countNewline(code) 67 | endLine = startLine + codeLine - 1 68 | checkString = checkString.substring(endIndex); 69 | keys.push({ 70 | "key": i, "code": code, "spec": spec, "hash": hash, 71 | "lines": codeLine, "start": startLine, "end": endLine}) 72 | start = endLine + 1 73 | }) 74 | console.log(keys); 75 | return keys 76 | } 77 | 78 | const opts = { 79 | "mode": "vega-lite", 80 | "renderer": "svg", 81 | "actions": {export: true, source: false, editor: false} 82 | }; 83 | 84 | let widgets = [] 85 | function update() { 86 | 87 | editor.operation(function(){ 88 | 89 | keys = _keys(editor.getValue()); 90 | 91 | // ENTER + UPDATE - Add all new widgets and Update Vis if changed 92 | keys.forEach(function(key, i){ 93 | let endLine = key.end 94 | let spec = key.spec 95 | let el; 96 | console.log(editor.lineInfo(endLine)[widgets]) 97 | // ENTER - Add new widget when none exists 98 | if (editor.lineInfo(endLine).widgets === undefined) { 99 | el = document.createElement("div"); 100 | el.style.minHeight = 256 + 'px'; 101 | elVis = el.appendChild(document.createElement("div")); 102 | elVis.id = "vis-editor-" + i; 103 | elVis.setAttribute('data-hash', key.hash); 104 | editor.addLineWidget(endLine, el); 105 | vegaEmbed(elVis, spec, opts) 106 | console.log(el); 107 | } else { 108 | node = editor.lineInfo(endLine).widgets[0].node 109 | console.log(node) 110 | hash = node.getAttribute('data-hash') 111 | console.log(hash, key.hash) 112 | if (hash != key.hash) { 113 | node.setAttribute('data-hash', key.hash); 114 | vegaEmbed(node, spec, opts); 115 | } 116 | } 117 | }) 118 | 119 | // EXIT - Remove all widgets that should no longer exist 120 | 121 | 122 | }) 123 | 124 | } 125 | 126 | 127 | // Returns a function, that, as long as it continues to be invoked, will not 128 | // be triggered. The function will be called after it stops being called for 129 | // N milliseconds. If `immediate` is passed, trigger the function on the 130 | // leading edge, instead of the trailing. 131 | function _debounce(func, wait, immediate) { 132 | var timeout; 133 | return function() { 134 | var context = this, args = arguments; 135 | var later = function() { 136 | timeout = null; 137 | if (!immediate) func.apply(context, args); 138 | }; 139 | var callNow = immediate && !timeout; 140 | clearTimeout(timeout); 141 | timeout = setTimeout(later, wait); 142 | if (callNow) func.apply(context, args); 143 | }; 144 | }; 145 | 146 | 147 | 148 | window.onload = function () { 149 | 150 | // Need to have vega, vega-lite and marked as dependencies 151 | const vega = window.vega 152 | const vl = window.vl 153 | const marked = window.marked 154 | const YAML = window.yaml 155 | 156 | // Codemirror setup 157 | let sc = document.getElementById("input-text"); 158 | let content = sc.textContent || sc.innerText || sc.innerHTML; 159 | 160 | window.editor = CodeMirror.fromTextArea(sc, { 161 | lineNumbers: false, 162 | lineWrapping: true, 163 | mode: "markdown", 164 | value: content, 165 | }); 166 | 167 | function _getChapter () { 168 | let hash = window.location.hash 169 | let file = hash.replace("#", ""); 170 | let fileName = file == "" ? "intro.md" : file + ".md"; 171 | let fileUrl = "pages/" + fileName; 172 | 173 | fetch(fileUrl).then(data => data.text()).then(data => { 174 | editor.setValue(data); 175 | }); 176 | } 177 | 178 | window.onhashchange = function () {_getChapter();} 179 | _getChapter(); 180 | 181 | text = editor.getValue() 182 | elInput = document.getElementById("input"); 183 | elCodemirror = editor.getWrapperElement() 184 | elOutput = document.getElementById("output"); 185 | elEditor = document.getElementById("editor"); 186 | elView = document.getElementById("view") 187 | elEdit = document.getElementById("edit") 188 | elContrast = document.getElementById("contrast") 189 | 190 | // function changeContrast( event ){ 191 | // elEditor.style.backgroundColor = "white"; 192 | 193 | // } 194 | 195 | // let darkLayout = false; 196 | // function changeContrast ( event ) { 197 | // if ( darkLayout === false ) { 198 | // document.body.className = 'yang'; 199 | // elCodemirror.style.backgroundColor = "#111" 200 | // elCodemirror.style.color = "#FDFDFD" 201 | // } else { 202 | // document.body.className = 'yin'; 203 | // elCodemirror.style.backgroundColor = "#FDFDFD" 204 | // elCodemirror.style.color = "#111" 205 | // } 206 | // console.log(darkLayout) 207 | // darkLayout = !darkLayout; 208 | // } 209 | 210 | function showOutput( event ) { 211 | console.log("showOutput") 212 | elView.style.display = "none" 213 | elEdit.style.display = "block" 214 | elInput.style.display = "none"; 215 | elOutput.style.display = "block"; 216 | visdown(text, elOutput); 217 | } 218 | 219 | function showInput( event) { 220 | elView.style.display = "block" 221 | elEdit.style.display = "none" 222 | elInput.style.display = "block"; 223 | elOutput.style.display = "none"; 224 | } 225 | 226 | elView.onclick = showOutput 227 | elEdit.onclick = showInput 228 | // elContrast.onclick = changeContrast 229 | 230 | var waiting; 231 | //Run on editor change 232 | editor.on("change", function() { 233 | text = editor.getValue(); 234 | clearTimeout(waiting); 235 | waiting = setTimeout(update, 500); 236 | }); 237 | 238 | //setTimeout(update, 100); 239 | 240 | } -------------------------------------------------------------------------------- /static/css/codemirror.css: -------------------------------------------------------------------------------- 1 | /* BASICS */ 2 | 3 | .CodeMirror { 4 | /* Set height, width, borders, and global font properties here */ 5 | font-family: monospace; 6 | height: 300px; 7 | color: black; 8 | } 9 | 10 | /* PADDING */ 11 | 12 | .CodeMirror-lines { 13 | padding: 4px 0; /* Vertical padding around content */ 14 | } 15 | .CodeMirror pre { 16 | padding: 0 4px; /* Horizontal padding of content */ 17 | } 18 | 19 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 20 | background-color: white; /* The little square between H and V scrollbars */ 21 | } 22 | 23 | /* GUTTER */ 24 | 25 | .CodeMirror-gutters { 26 | border-right: 1px solid #ddd; 27 | background-color: #f7f7f7; 28 | white-space: nowrap; 29 | } 30 | .CodeMirror-linenumbers {} 31 | .CodeMirror-linenumber { 32 | padding: 0 3px 0 5px; 33 | min-width: 20px; 34 | text-align: right; 35 | color: #999; 36 | white-space: nowrap; 37 | } 38 | 39 | .CodeMirror-guttermarker { color: black; } 40 | .CodeMirror-guttermarker-subtle { color: #999; } 41 | 42 | /* CURSOR */ 43 | 44 | .CodeMirror-cursor { 45 | border-left: 1px solid black; 46 | border-right: none; 47 | width: 0; 48 | } 49 | /* Shown when moving in bi-directional text */ 50 | .CodeMirror div.CodeMirror-secondarycursor { 51 | border-left: 1px solid silver; 52 | } 53 | .cm-fat-cursor .CodeMirror-cursor { 54 | width: auto; 55 | border: 0 !important; 56 | background: #7e7; 57 | } 58 | .cm-fat-cursor div.CodeMirror-cursors { 59 | z-index: 1; 60 | } 61 | 62 | .cm-animate-fat-cursor { 63 | width: auto; 64 | border: 0; 65 | -webkit-animation: blink 1.06s steps(1) infinite; 66 | -moz-animation: blink 1.06s steps(1) infinite; 67 | animation: blink 1.06s steps(1) infinite; 68 | background-color: #7e7; 69 | } 70 | @-moz-keyframes blink { 71 | 0% {} 72 | 50% { background-color: transparent; } 73 | 100% {} 74 | } 75 | @-webkit-keyframes blink { 76 | 0% {} 77 | 50% { background-color: transparent; } 78 | 100% {} 79 | } 80 | @keyframes blink { 81 | 0% {} 82 | 50% { background-color: transparent; } 83 | 100% {} 84 | } 85 | 86 | /* Can style cursor different in overwrite (non-insert) mode */ 87 | .CodeMirror-overwrite .CodeMirror-cursor {} 88 | 89 | .cm-tab { display: inline-block; text-decoration: inherit; } 90 | 91 | .CodeMirror-rulers { 92 | position: absolute; 93 | left: 0; right: 0; top: -50px; bottom: -20px; 94 | overflow: hidden; 95 | } 96 | .CodeMirror-ruler { 97 | border-left: 1px solid #ccc; 98 | top: 0; bottom: 0; 99 | position: absolute; 100 | } 101 | 102 | /* DEFAULT THEME */ 103 | 104 | .cm-s-default .cm-header {color: blue;} 105 | .cm-s-default .cm-quote {color: #090;} 106 | .cm-negative {color: #d44;} 107 | .cm-positive {color: #292;} 108 | .cm-header, .cm-strong {font-weight: bold;} 109 | .cm-em {font-style: italic;} 110 | .cm-link {text-decoration: underline;} 111 | .cm-strikethrough {text-decoration: line-through;} 112 | 113 | .cm-s-default .cm-keyword {color: #708;} 114 | .cm-s-default .cm-atom {color: #219;} 115 | .cm-s-default .cm-number {color: #164;} 116 | .cm-s-default .cm-def {color: #00f;} 117 | .cm-s-default .cm-variable, 118 | .cm-s-default .cm-punctuation, 119 | .cm-s-default .cm-property, 120 | .cm-s-default .cm-operator {} 121 | .cm-s-default .cm-variable-2 {color: #05a;} 122 | .cm-s-default .cm-variable-3 {color: #085;} 123 | .cm-s-default .cm-comment {color: #a50;} 124 | .cm-s-default .cm-string {color: #a11;} 125 | .cm-s-default .cm-string-2 {color: #f50;} 126 | .cm-s-default .cm-meta {color: #555;} 127 | .cm-s-default .cm-qualifier {color: #555;} 128 | .cm-s-default .cm-builtin {color: #30a;} 129 | .cm-s-default .cm-bracket {color: #997;} 130 | .cm-s-default .cm-tag {color: #170;} 131 | .cm-s-default .cm-attribute {color: #00c;} 132 | .cm-s-default .cm-hr {color: #999;} 133 | .cm-s-default .cm-link {color: #00c;} 134 | 135 | .cm-s-default .cm-error {color: #f00;} 136 | .cm-invalidchar {color: #f00;} 137 | 138 | .CodeMirror-composing { border-bottom: 2px solid; } 139 | 140 | /* Default styles for common addons */ 141 | 142 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} 143 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} 144 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } 145 | .CodeMirror-activeline-background {background: #e8f2ff;} 146 | 147 | /* STOP */ 148 | 149 | /* The rest of this file contains styles related to the mechanics of 150 | the editor. You probably shouldn't touch them. */ 151 | 152 | .CodeMirror { 153 | position: relative; 154 | overflow: hidden; 155 | background: white; 156 | } 157 | 158 | .CodeMirror-scroll { 159 | overflow: scroll !important; /* Things will break if this is overridden */ 160 | /* 30px is the magic margin used to hide the element's real scrollbars */ 161 | /* See overflow: hidden in .CodeMirror */ 162 | margin-bottom: -30px; margin-right: -30px; 163 | padding-bottom: 30px; 164 | height: 100%; 165 | outline: none; /* Prevent dragging from highlighting the element */ 166 | position: relative; 167 | } 168 | .CodeMirror-sizer { 169 | position: relative; 170 | border-right: 30px solid transparent; 171 | } 172 | 173 | /* The fake, visible scrollbars. Used to force redraw during scrolling 174 | before actual scrolling happens, thus preventing shaking and 175 | flickering artifacts. */ 176 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 177 | position: absolute; 178 | z-index: 6; 179 | display: none; 180 | } 181 | .CodeMirror-vscrollbar { 182 | right: 0; top: 0; 183 | overflow-x: hidden; 184 | overflow-y: scroll; 185 | } 186 | .CodeMirror-hscrollbar { 187 | bottom: 0; left: 0; 188 | overflow-y: hidden; 189 | overflow-x: scroll; 190 | } 191 | .CodeMirror-scrollbar-filler { 192 | right: 0; bottom: 0; 193 | } 194 | .CodeMirror-gutter-filler { 195 | left: 0; bottom: 0; 196 | } 197 | 198 | .CodeMirror-gutters { 199 | position: absolute; left: 0; top: 0; 200 | min-height: 100%; 201 | z-index: 3; 202 | } 203 | .CodeMirror-gutter { 204 | white-space: normal; 205 | height: 100%; 206 | display: inline-block; 207 | vertical-align: top; 208 | margin-bottom: -30px; 209 | } 210 | .CodeMirror-gutter-wrapper { 211 | position: absolute; 212 | z-index: 4; 213 | background: none !important; 214 | border: none !important; 215 | } 216 | .CodeMirror-gutter-background { 217 | position: absolute; 218 | top: 0; bottom: 0; 219 | z-index: 4; 220 | } 221 | .CodeMirror-gutter-elt { 222 | position: absolute; 223 | cursor: default; 224 | z-index: 4; 225 | } 226 | .CodeMirror-gutter-wrapper { 227 | -webkit-user-select: none; 228 | -moz-user-select: none; 229 | user-select: none; 230 | } 231 | 232 | .CodeMirror-lines { 233 | cursor: text; 234 | min-height: 1px; /* prevents collapsing before first draw */ 235 | } 236 | .CodeMirror pre { 237 | /* Reset some styles that the rest of the page might have set */ 238 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; 239 | border-width: 0; 240 | background: transparent; 241 | font-family: inherit; 242 | font-size: inherit; 243 | margin: 0; 244 | white-space: pre; 245 | word-wrap: normal; 246 | line-height: inherit; 247 | color: inherit; 248 | z-index: 2; 249 | position: relative; 250 | overflow: visible; 251 | -webkit-tap-highlight-color: transparent; 252 | -webkit-font-variant-ligatures: contextual; 253 | font-variant-ligatures: contextual; 254 | } 255 | .CodeMirror-wrap pre { 256 | word-wrap: break-word; 257 | white-space: pre-wrap; 258 | word-break: normal; 259 | } 260 | 261 | .CodeMirror-linebackground { 262 | position: absolute; 263 | left: 0; right: 0; top: 0; bottom: 0; 264 | z-index: 0; 265 | } 266 | 267 | .CodeMirror-linewidget { 268 | position: relative; 269 | z-index: 2; 270 | overflow: auto; 271 | } 272 | 273 | .CodeMirror-widget {} 274 | 275 | .CodeMirror-code { 276 | outline: none; 277 | } 278 | 279 | /* Force content-box sizing for the elements where we expect it */ 280 | .CodeMirror-scroll, 281 | .CodeMirror-sizer, 282 | .CodeMirror-gutter, 283 | .CodeMirror-gutters, 284 | .CodeMirror-linenumber { 285 | -moz-box-sizing: content-box; 286 | box-sizing: content-box; 287 | } 288 | 289 | .CodeMirror-measure { 290 | position: absolute; 291 | width: 100%; 292 | height: 0; 293 | overflow: hidden; 294 | visibility: hidden; 295 | } 296 | 297 | .CodeMirror-cursor { 298 | position: absolute; 299 | pointer-events: none; 300 | } 301 | .CodeMirror-measure pre { position: static; } 302 | 303 | div.CodeMirror-cursors { 304 | visibility: hidden; 305 | position: relative; 306 | z-index: 3; 307 | } 308 | div.CodeMirror-dragcursors { 309 | visibility: visible; 310 | } 311 | 312 | .CodeMirror-focused div.CodeMirror-cursors { 313 | visibility: visible; 314 | } 315 | 316 | .CodeMirror-selected { background: #d9d9d9; } 317 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } 318 | .CodeMirror-crosshair { cursor: crosshair; } 319 | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } 320 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } 321 | 322 | .cm-searching { 323 | background: #ffa; 324 | background: rgba(255, 255, 0, .4); 325 | } 326 | 327 | /* Used to force a border model for a node */ 328 | .cm-force-border { padding-right: .1px; } 329 | 330 | @media print { 331 | /* Hide the cursor when printing */ 332 | .CodeMirror div.CodeMirror-cursors { 333 | visibility: hidden; 334 | } 335 | } 336 | 337 | /* See issue #2901 */ 338 | .cm-tab-wrap-hack:after { content: ''; } 339 | 340 | /* Help users use markselection to safely style text background */ 341 | span.CodeMirror-selectedtext { background: none; } 342 | -------------------------------------------------------------------------------- /static/css/github-markdown.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:octicons-link;src:url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff')}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.5;color:#24292e;font-family:-apple-system,system-ui,BlinkMacSystemFont,segoe ui,Helvetica,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body .pl-c{color:#969896}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#0086b3}.markdown-body .pl-e,.markdown-body .pl-en{color:#795da3}.markdown-body .pl-smi,.markdown-body .pl-s .pl-s1{color:#333}.markdown-body .pl-ent{color:#63a35c}.markdown-body .pl-k{color:#a71d5d}.markdown-body .pl-s,.markdown-body .pl-pds,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sre,.markdown-body .pl-sr .pl-sra{color:#183691}.markdown-body .pl-v,.markdown-body .pl-smw{color:#ed6a43}.markdown-body .pl-bu{color:#b52a1d}.markdown-body .pl-ii{color:#f8f8f8;background-color:#b52a1d}.markdown-body .pl-c2{color:#f8f8f8;background-color:#b52a1d}.markdown-body .pl-c2::before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#63a35c}.markdown-body .pl-ml{color:#693a17}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#1d3e81}.markdown-body .pl-mq{color:teal}.markdown-body .pl-mi{font-style:italic;color:#333}.markdown-body .pl-mb{font-weight:700;color:#333}.markdown-body .pl-md{color:#bd2c00;background-color:#ffecec}.markdown-body .pl-mi1{color:#55a532;background-color:#eaffea}.markdown-body .pl-mc{color:#ef9700;background-color:#ffe3b4}.markdown-body .pl-mi2{color:#d8d8d8;background-color:gray}.markdown-body .pl-mdr{font-weight:700;color:#795da3}.markdown-body .pl-mo{color:#1d3e81}.markdown-body .pl-ba{color:#595e62}.markdown-body .pl-sg{color:silver}.markdown-body .pl-corl{text-decoration:underline;color:#183691}.markdown-body .octicon{display:inline-block;vertical-align:text-top;fill:currentColor}.markdown-body a{background-color:transparent;-webkit-text-decoration-skip:objects}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit}.markdown-body strong{font-weight:bolder}.markdown-body h1{font-size:2em;margin:.67em 0}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{box-sizing:content-box;height:0;overflow:visible}.markdown-body input{font:inherit;margin:0}.markdown-body input{overflow:visible}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #dfe2e5}.markdown-body hr::before{display:table;content:""}.markdown-body hr::after{display:table;clear:both;content:""}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px;font-weight:600}.markdown-body h2{font-size:24px;font-weight:600}.markdown-body h3{font-size:20px;font-weight:600}.markdown-body h4{font-size:16px;font-weight:600}.markdown-body h5{font-size:14px;font-weight:600}.markdown-body h6{font-size:12px;font-weight:600}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ul,.markdown-body ol{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ul ul ol,.markdown-body ul ol ol,.markdown-body ol ul ol,.markdown-body ol ol ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code{font-family:sfmono-regular,Consolas,liberation mono,Menlo,Courier,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0;font:12px sfmono-regular,Consolas,liberation mono,Menlo,Courier,monospace}.markdown-body .octicon{vertical-align:text-bottom}.markdown-body .pl-0{padding-left:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .pl-3{padding-left:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body::before{display:table;content:""}.markdown-body::after{display:table;clear:both;content:""}.markdown-body>*:first-child{margin-top:0!important}.markdown-body>*:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:0}.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:solid 1px #c6cbd1;border-bottom-color:#959da5;border-radius:3px;box-shadow:inset 0 -1px 0 #959da5}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1{padding-bottom:.3em;font-size:2em;border-bottom:1px solid #eaecef}.markdown-body h2{padding-bottom:.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ul,.markdown-body ol{padding-left:2em}.markdown-body ul ul,.markdown-body ul ol,.markdown-body ol ol,.markdown-body ol ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table th,.markdown-body table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body code{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body code::before,.markdown-body code::after{letter-spacing:-.2em;content:"\00a0"}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body pre code::before,.markdown-body pre code::after{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px sfmono-regular,Consolas,liberation mono,Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fcfcfc;border:solid 1px #c6cbd1;border-bottom-color:#959da5;border-radius:3px;box-shadow:inset 0 -1px 0 #959da5}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee} -------------------------------------------------------------------------------- /data/notes.csv: -------------------------------------------------------------------------------- 1 | year,money,type,denom,value,number 2 | 1977,2.72,Notes,0001,1,2.72 3 | 1977,0.55,Notes,1000,1000,0.001 4 | 1977,1.48,Notes,0002,2,0.74 5 | 1977,9.95,Notes,0050,50,0.199 6 | 1977,6.9,Notes,0020,20,0.345 7 | 1977,43.02,Notes,0100,100,0.43 8 | 1977,,Notes,0500,500, 9 | 1977,18.25,Notes,0010,10,1.825 10 | 1977,5.72,Notes,0005,5,1.144 11 | 1978,,Notes,0500,500, 12 | 1978,19.57,Notes,0010,10,1.957 13 | 1978,14.4,Notes,0050,50,0.288 14 | 1978,5.76,Notes,0005,5,1.152 15 | 1978,7.79,Notes,0020,20,0.39 16 | 1978,2.56,Notes,0001,1,2.56 17 | 1978,,Notes,1000,1000, 18 | 1978,53.69,Notes,0100,100,0.537 19 | 1978,1.74,Notes,0002,2,0.87 20 | 1979,59.51,Notes,0100,100,0.595 21 | 1979,,Notes,1000,1000, 22 | 1979,9.61,Notes,0020,20,0.48 23 | 1979,2.15,Notes,0002,2,1.075 24 | 1979,5.88,Notes,0005,5,1.176 25 | 1979,19.83,Notes,0050,50,0.397 26 | 1979,,Notes,0500,500, 27 | 1979,21.23,Notes,0010,10,2.123 28 | 1979,2.14,Notes,0001,1,2.14 29 | 1980,6.34,Notes,0005,5,1.268 30 | 1980,74.06,Notes,0100,100,0.741 31 | 1980,,Notes,0500,500, 32 | 1980,20.97,Notes,0010,10,2.097 33 | 1980,,Notes,1000,1000, 34 | 1980,2.99,Notes,0002,2,1.495 35 | 1980,2.07,Notes,0001,1,2.07 36 | 1980,10.9,Notes,0020,20,0.545 37 | 1980,22.06,Notes,0050,50,0.441 38 | 1981,,Notes,1000,1000, 39 | 1981,6.92,Notes,0005,5,1.384 40 | 1981,2.12,Notes,0001,1,2.12 41 | 1981,,Notes,0500,500, 42 | 1981,27.24,Notes,0050,50,0.545 43 | 1981,19.91,Notes,0010,10,1.991 44 | 1981,78.29,Notes,0100,100,0.783 45 | 1981,3.92,Notes,0002,2,1.96 46 | 1981,12.14,Notes,0020,20,0.607 47 | 1982,,Notes,1000,1000, 48 | 1982,30.17,Notes,0050,50,0.603 49 | 1982,97.77,Notes,0100,100,0.978 50 | 1982,2.05,Notes,0001,1,2.05 51 | 1982,,Notes,0500,500, 52 | 1982,17.98,Notes,0010,10,1.798 53 | 1982,14.33,Notes,0020,20,0.716 54 | 1982,4.31,Notes,0002,2,2.155 55 | 1982,8.07,Notes,0005,5,1.614 56 | 1983,5.6,Notes,0005,5,1.12 57 | 1983,1.98,Notes,0001,1,1.98 58 | 1983,4.5,Notes,0002,2,2.25 59 | 1983,,Notes,1000,1000, 60 | 1983,14.63,Notes,0020,20,0.732 61 | 1983,36.26,Notes,0050,50,0.725 62 | 1983,116.9,Notes,0100,100,1.169 63 | 1983,,Notes,0500,500, 64 | 1983,17.7,Notes,0010,10,1.77 65 | 1984,,Notes,1000,1000, 66 | 1984,2.04,Notes,0001,1,2.04 67 | 1984,39.2,Notes,0050,50,0.784 68 | 1984,,Notes,0500,500, 69 | 1984,22.17,Notes,0010,10,2.217 70 | 1984,12.34,Notes,0005,5,2.468 71 | 1984,139.04,Notes,0100,100,1.39 72 | 1984,16.36,Notes,0020,20,0.818 73 | 1984,5.8,Notes,0002,2,2.9 74 | 1985,25.36,Notes,0010,10,2.536 75 | 1985,,Notes,1000,1000, 76 | 1985,6.5,Notes,0002,2,3.25 77 | 1985,13.03,Notes,0005,5,2.606 78 | 1985,2.38,Notes,0001,1,2.38 79 | 1985,17.84,Notes,0020,20,0.892 80 | 1985,43.1,Notes,0050,50,0.862 81 | 1985,150.18,Notes,0100,100,1.502 82 | 1985,,Notes,0500,500, 83 | 1986,52.47,Notes,0050,50,1.049 84 | 1986,25.1,Notes,0010,10,2.51 85 | 1986,18.99,Notes,0020,20,0.949 86 | 1986,171.16,Notes,0100,100,1.712 87 | 1986,12.87,Notes,0005,5,2.574 88 | 1986,6.83,Notes,0002,2,3.415 89 | 1986,,Notes,1000,1000, 90 | 1986,,Notes,0500,500, 91 | 1986,3.01,Notes,0001,1,3.01 92 | 1987,1.8,Notes,0500,500,0.004 93 | 1987,6.53,Notes,0002,2,3.265 94 | 1987,28.25,Notes,0010,10,2.825 95 | 1987,190.77,Notes,0100,100,1.908 96 | 1987,,Notes,1000,1000, 97 | 1987,72.67,Notes,0050,50,1.453 98 | 1987,14.29,Notes,0005,5,2.858 99 | 1987,23.31,Notes,0020,20,1.166 100 | 1987,3.52,Notes,0001,1,3.52 101 | 1988,3.6,Notes,0001,1,3.6 102 | 1988,14.82,Notes,0005,5,2.964 103 | 1988,29.96,Notes,0010,10,2.996 104 | 1988,,Notes,1000,1000, 105 | 1988,6.81,Notes,0002,2,3.405 106 | 1988,212.08,Notes,0100,100,2.121 107 | 1988,26.13,Notes,0020,20,1.306 108 | 1988,2.3,Notes,0500,500,0.005 109 | 1988,94.59,Notes,0050,50,1.892 110 | 1989,17.39,Notes,0005,5,3.478 111 | 1989,35.15,Notes,0010,10,3.515 112 | 1989,31.0,Notes,0020,20,1.55 113 | 1989,12.57,Notes,0500,500,0.025 114 | 1989,125.53,Notes,0050,50,2.511 115 | 1989,237.78,Notes,0100,100,2.378 116 | 1989,,Notes,1000,1000, 117 | 1989,3.48,Notes,0001,1,3.48 118 | 1989,8.04,Notes,0002,2,4.02 119 | 1990,,Notes,1000,1000, 120 | 1990,3.35,Notes,0001,1,3.35 121 | 1990,29.52,Notes,0020,20,1.476 122 | 1990,148.12,Notes,0050,50,2.962 123 | 1990,37.85,Notes,0010,10,3.785 124 | 1990,245.7,Notes,0100,100,2.457 125 | 1990,21.77,Notes,0500,500,0.044 126 | 1990,18.1,Notes,0005,5,3.62 127 | 1990,8.83,Notes,0002,2,4.415 128 | 1991,9.42,Notes,0002,2,4.71 129 | 1991,18.54,Notes,0500,500,0.037 130 | 1991,27.43,Notes,0020,20,1.372 131 | 1991,24.0,Notes,0005,5,4.8 132 | 1991,177.19,Notes,0050,50,3.544 133 | 1991,52.02,Notes,0010,10,5.202 134 | 1991,3.35,Notes,0001,1,3.35 135 | 1991,322.66,Notes,0100,100,3.227 136 | 1991,,Notes,1000,1000, 137 | 1992,49.1,Notes,0500,500,0.098 138 | 1992,225.77,Notes,0050,50,4.515 139 | 1992,3.35,Notes,0001,1,3.35 140 | 1992,42.85,Notes,0010,10,4.285 141 | 1992,20.22,Notes,0005,5,4.044 142 | 1992,23.4,Notes,0020,20,1.17 143 | 1992,7.2,Notes,0002,2,3.6 144 | 1992,,Notes,1000,1000, 145 | 1992,326.63,Notes,0100,100,3.266 146 | 1993,,Notes,1000,1000, 147 | 1993,3.28,Notes,0001,1,3.28 148 | 1993,18.6,Notes,0005,5,3.72 149 | 1993,16.31,Notes,0020,20,0.815 150 | 1993,377.84,Notes,0100,100,3.778 151 | 1993,6.24,Notes,0002,2,3.12 152 | 1993,53.34,Notes,0010,10,5.334 153 | 1993,249.91,Notes,0050,50,4.998 154 | 1993,113.03,Notes,0500,500,0.226 155 | 1994,464.57,Notes,0100,100,4.646 156 | 1994,285.37,Notes,0050,50,5.707 157 | 1994,6.02,Notes,0002,2,3.01 158 | 1994,,Notes,1000,1000, 159 | 1994,11.2,Notes,0020,20,0.56 160 | 1994,3.2,Notes,0001,1,3.2 161 | 1994,168.82,Notes,0500,500,0.338 162 | 1994,69.43,Notes,0010,10,6.943 163 | 1994,17.65,Notes,0005,5,3.53 164 | 1995,5.15,Notes,0002,2,2.575 165 | 1995,208.73,Notes,0500,500,0.417 166 | 1995,551.05,Notes,0100,100,5.51 167 | 1995,92.18,Notes,0010,10,9.218 168 | 1995,3.22,Notes,0001,1,3.22 169 | 1995,,Notes,1000,1000, 170 | 1995,316.59,Notes,0050,50,6.332 171 | 1995,16.51,Notes,0005,5,3.302 172 | 1995,7.18,Notes,0020,20,0.359 173 | 1996,626.0,Notes,0100,100,6.26 174 | 1996,242.7,Notes,0500,500,0.485 175 | 1996,,Notes,1000,1000, 176 | 1996,336.23,Notes,0050,50,6.725 177 | 1996,7.03,Notes,0020,20,0.352 178 | 1996,15.54,Notes,0005,5,3.108 179 | 1996,3.16,Notes,0001,1,3.16 180 | 1996,5.27,Notes,0002,2,2.635 181 | 1996,110.63,Notes,0010,10,11.063 182 | 1997,3.19,Notes,0001,1,3.19 183 | 1997,,Notes,1000,1000, 184 | 1997,342.45,Notes,0050,50,6.849 185 | 1997,5.5,Notes,0002,2,2.75 186 | 1997,14.27,Notes,0005,5,2.854 187 | 1997,701.59,Notes,0100,100,7.016 188 | 1997,9.79,Notes,0020,20,0.489 189 | 1997,279.75,Notes,0500,500,0.56 190 | 1997,124.12,Notes,0010,10,12.412 191 | 1998,333.16,Notes,0050,50,6.663 192 | 1998,12.9,Notes,0005,5,2.58 193 | 1998,448.27,Notes,0500,500,0.897 194 | 1998,5.3,Notes,0002,2,2.65 195 | 1998,,Notes,1000,1000, 196 | 1998,129.9,Notes,0010,10,12.99 197 | 1998,8.99,Notes,0020,20,0.45 198 | 1998,3.16,Notes,0001,1,3.16 199 | 1998,781.97,Notes,0100,100,7.82 200 | 1999,132.82,Notes,0010,10,13.282 201 | 1999,11.52,Notes,0005,5,2.304 202 | 1999,,Notes,1000,1000, 203 | 1999,3.08,Notes,0001,1,3.08 204 | 1999,5.12,Notes,0002,2,2.56 205 | 1999,858.31,Notes,0100,100,8.583 206 | 1999,572.5,Notes,0500,500,1.145 207 | 1999,10.1,Notes,0020,20,0.505 208 | 1999,332.3,Notes,0050,50,6.646 209 | 2000,328.18,Notes,0050,50,6.564 210 | 2000,529.47,Notes,0500,500,1.059 211 | 2000,123.36,Notes,0010,10,12.336 212 | 2000,10.16,Notes,0005,5,2.032 213 | 2000,4.71,Notes,0002,2,2.355 214 | 2000,10.12,Notes,0020,20,0.506 215 | 2000,1081.41,Notes,0100,100,10.814 216 | 2000,37.19,Notes,1000,1000,0.037 217 | 2000,3.07,Notes,0001,1,3.07 218 | 2001,15.31,Notes,0020,20,0.766 219 | 2001,1180.41,Notes,0100,100,11.804 220 | 2001,71.79,Notes,1000,1000,0.072 221 | 2001,356.01,Notes,0050,50,7.12 222 | 2001,3.08,Notes,0001,1,3.08 223 | 2001,685.12,Notes,0500,500,1.37 224 | 2001,12.64,Notes,0005,5,2.528 225 | 2001,5.38,Notes,0002,2,2.69 226 | 2001,119.89,Notes,0010,10,11.989 227 | 2002,17.39,Notes,0005,5,3.478 228 | 2002,1153.86,Notes,0100,100,11.539 229 | 2002,4.83,Notes,0002,2,2.415 230 | 2002,938.13,Notes,0500,500,1.876 231 | 2002,351.91,Notes,0050,50,7.038 232 | 2002,159.71,Notes,1000,1000,0.16 233 | 2002,3.05,Notes,0001,1,3.05 234 | 2002,34.25,Notes,0020,20,1.712 235 | 2002,90.88,Notes,0010,10,9.088 236 | 2003,1214.42,Notes,0100,100,12.144 237 | 2003,2.99,Notes,0001,1,2.99 238 | 2003,330.27,Notes,0050,50,6.605 239 | 2003,43.83,Notes,0020,20,2.192 240 | 2003,77.5,Notes,0010,10,7.75 241 | 2003,274.73,Notes,1000,1000,0.275 242 | 2003,4.72,Notes,0002,2,2.36 243 | 2003,1229.38,Notes,0500,500,2.459 244 | 2003,22.76,Notes,0005,5,4.552 245 | 2004,1527.28,Notes,0500,500,3.055 246 | 2004,2.99,Notes,0001,1,2.99 247 | 2004,38.76,Notes,0020,20,1.938 248 | 2004,4.62,Notes,0002,2,2.31 249 | 2004,67.7,Notes,0010,10,6.77 250 | 2004,299.41,Notes,0050,50,5.988 251 | 2004,1232.82,Notes,0100,100,12.328 252 | 2004,20.86,Notes,0005,5,4.172 253 | 2004,420.82,Notes,1000,1000,0.421 254 | 2005,40.77,Notes,0020,20,2.038 255 | 2005,1346.37,Notes,0100,100,13.464 256 | 2005,2.99,Notes,0001,1,2.99 257 | 2005,19.8,Notes,0005,5,3.96 258 | 2005,62.74,Notes,0010,10,6.274 259 | 2005,4.51,Notes,0002,2,2.255 260 | 2005,278.42,Notes,0050,50,5.568 261 | 2005,1823.32,Notes,0500,500,3.647 262 | 2005,643.46,Notes,1000,1000,0.643 263 | 2006,936.76,Notes,1000,1000,0.937 264 | 2006,3.01,Notes,0001,1,3.01 265 | 2006,2254.0,Notes,0500,500,4.508 266 | 2006,4.47,Notes,0002,2,2.235 267 | 2006,1354.44,Notes,0100,100,13.544 268 | 2006,18.87,Notes,0005,5,3.774 269 | 2006,279.51,Notes,0050,50,5.59 270 | 2006,71.55,Notes,0010,10,7.155 271 | 2006,41.78,Notes,0020,20,2.089 272 | 2007,1345.75,Notes,0100,100,13.458 273 | 2007,21.11,Notes,0005,5,4.222 274 | 2007,2631.08,Notes,0500,500,5.262 275 | 2007,6.36,Notes,0002,2,3.18 276 | 2007,265.08,Notes,0050,50,5.302 277 | 2007,41.08,Notes,0020,20,2.054 278 | 2007,93.33,Notes,0010,10,9.333 279 | 2007,3.0,Notes,0001,1,3.0 280 | 2007,1412.19,Notes,1000,1000,1.412 281 | 2008,1370.28,Notes,0100,100,13.703 282 | 2008,122.22,Notes,0010,10,12.222 283 | 2008,1917.84,Notes,1000,1000,1.918 284 | 2008,6.65,Notes,0002,2,3.325 285 | 2008,244.4,Notes,0050,50,4.888 286 | 2008,43.99,Notes,0020,20,2.2 287 | 2008,3.0,Notes,0001,1,3.0 288 | 2008,22.71,Notes,0005,5,4.542 289 | 2008,3083.04,Notes,0500,500,6.166 290 | 2009,210.57,Notes,0050,50,4.211 291 | 2009,3644.79,Notes,0500,500,7.29 292 | 2009,1383.64,Notes,0100,100,13.836 293 | 2009,22.33,Notes,0005,5,4.466 294 | 2009,185.36,Notes,0010,10,18.536 295 | 2009,6.98,Notes,0002,2,3.49 296 | 2009,2382.52,Notes,1000,1000,2.383 297 | 2009,2.99,Notes,0001,1,2.99 298 | 2009,46.81,Notes,0020,20,2.34 299 | 2010,4453.11,Notes,0500,500,8.906 300 | 2010,159.8,Notes,0050,50,3.196 301 | 2010,60.4,Notes,0020,20,3.02 302 | 2010,212.88,Notes,0010,10,21.288 303 | 2010,1402.43,Notes,0100,100,14.024 304 | 2010,3027.13,Notes,1000,1000,3.027 305 | 2010,8.51,Notes,0002,2,4.255 306 | 2010,34.3,Notes,0005,5,6.86 307 | 2010,2.99,Notes,0001,1,2.99 308 | 2011,2.99,Notes,0001,1,2.99 309 | 2011,36.43,Notes,0005,5,7.286 310 | 2011,5128.07,Notes,0500,500,10.256 311 | 2011,174.38,Notes,0050,50,3.488 312 | 2011,8.51,Notes,0002,2,4.255 313 | 2011,3468.81,Notes,1000,1000,3.469 314 | 2011,1411.88,Notes,0100,100,14.119 315 | 2011,230.02,Notes,0010,10,23.002 316 | 2011,70.2,Notes,0020,20,3.51 317 | 2012,76.5,Notes,0020,20,3.825 318 | 2012,251.68,Notes,0010,10,25.168 319 | 2012,4299.0,Notes,1000,1000,4.299 320 | 2012,5359.5,Notes,0500,500,10.719 321 | 2012,1442.1,Notes,0100,100,14.421 322 | 2012,8.51,Notes,0002,2,4.255 323 | 2012,173.05,Notes,0050,50,3.461 324 | 2012,36.87,Notes,0005,5,7.374 325 | 2012,2.99,Notes,0001,1,2.99 326 | 2013,2.99,Notes,0001,1,2.99 327 | 2013,5081.37,Notes,1000,1000,5.081 328 | 2013,1476.46,Notes,0100,100,14.765 329 | 2013,8.51,Notes,0002,2,4.255 330 | 2013,37.14,Notes,0005,5,7.428 331 | 2013,85.69,Notes,0020,20,4.284 332 | 2013,5702.48,Notes,0500,500,11.405 333 | 2013,266.48,Notes,0010,10,26.648 334 | 2013,172.42,Notes,0050,50,3.448 335 | 2014,2.99,Notes,0001,1,2.99 336 | 2014,1502.65,Notes,0100,100,15.026 337 | 2014,8.54,Notes,0002,2,4.27 338 | 2014,6563.91,Notes,0500,500,13.128 339 | 2014,5612.45,Notes,1000,1000,5.612 340 | 2014,303.04,Notes,0010,10,30.304 341 | 2014,37.02,Notes,0005,5,7.404 342 | 2014,86.99,Notes,0020,20,4.35 343 | 2014,174.36,Notes,0050,50,3.487 344 | 2015,36.8,Notes,0005,5,7.36 345 | 2015,194.5,Notes,0050,50,3.89 346 | 2015,8.53,Notes,0002,2,4.265 347 | 2015,1577.83,Notes,0100,100,15.778 348 | 2015,98.47,Notes,0020,20,4.924 349 | 2015,7853.75,Notes,0500,500,15.708 350 | 2015,3.09,Notes,0001,1,3.09 351 | 2015,320.15,Notes,0010,10,32.015 352 | 2015,6325.68,Notes,1000,1000,6.326 353 | -------------------------------------------------------------------------------- /static/lib/markdown.min.js: -------------------------------------------------------------------------------- 1 | !function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror"),require("../xml/xml"),require("../meta")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../xml/xml","../meta"],t):t(CodeMirror)}(function(t){"use strict";t.defineMode("markdown",function(e,i){function n(i){if(t.findModeByName){var n=t.findModeByName(i);n&&(i=n.mime||n.mimes[0])}var r=t.getMode(e,i);return"null"==r.name?null:r}function r(t,e,i){return e.f=e.inline=i,i(t,e)}function a(t,e,i){return e.f=e.block=i,i(t,e)}function l(t){return!t||!/\S/.test(t.string)}function o(t){return t.linkTitle=!1,t.em=!1,t.strong=!1,t.strikethrough=!1,t.quote=0,t.indentedCode=!1,t.f==s&&(t.f=f,t.block=h),t.trailingSpace=0,t.trailingSpaceNewLine=!1,t.prevLine=t.thisLine,t.thisLine={stream:null},null}function h(e,a){var o=e.column()===a.indentation,h=l(a.prevLine.stream),s=a.indentedCode,u=a.prevLine.hr,f=!1!==a.list,c=(a.listStack[a.listStack.length-1]||0)+3;a.indentedCode=!1;var d=a.indentation;if(null===a.indentationDiff&&(a.indentationDiff=a.indentation,f)){for(a.list=null;d=4&&(s||a.prevLine.fencedCodeEnd||a.prevLine.header||h))return e.skipToEnd(),a.indentedCode=!0,T.code;if(e.eatSpace())return null;if(o&&a.indentation<=c&&(S=e.match(E))&&S[1].length<=6)return a.quote=0,a.header=S[1].length,a.thisLine.header=!0,i.highlightFormatting&&(a.formatting="header"),a.f=a.inline,m(a);if(a.indentation<=c&&e.eat(">"))return a.quote=o?1:a.quote+1,i.highlightFormatting&&(a.formatting="quote"),e.eatSpace(),m(a);if(!x&&!a.setext&&o&&a.indentation<=c&&(S=e.match(M))){var v=S[1]?"ol":"ul";return a.indentation=d+e.current().length,a.list=!0,a.quote=0,a.listStack.push(a.indentation),i.taskLists&&e.match(b,!1)&&(a.taskList=!0),a.f=a.inline,i.highlightFormatting&&(a.formatting=["list","list-"+v]),m(a)}return o&&a.indentation<=c&&(S=e.match(y,!0))?(a.quote=0,a.fencedEndRE=new RegExp(S[1]+"+ *$"),a.localMode=i.fencedCodeBlockHighlighting&&n(S[2]),a.localMode&&(a.localState=t.startState(a.localMode)),a.f=a.block=g,i.highlightFormatting&&(a.formatting="code-block"),a.code=-1,m(a)):a.setext||!(k&&f||a.quote||!1!==a.list||a.code||x||C.test(e.string))&&(S=e.lookAhead(1))&&(S=S.match(w))?(a.setext?(a.header=a.setext,a.setext=0,e.skipToEnd(),i.highlightFormatting&&(a.formatting="header")):(a.header="="==S[0].charAt(0)?1:2,a.setext=a.header),a.thisLine.header=!0,a.f=a.inline,m(a)):x?(e.skipToEnd(),a.hr=!0,a.thisLine.hr=!0,T.hr):"["===e.peek()?r(e,a,p):r(e,a,a.inline)}function s(e,i){var n=v.token(e,i.htmlState);if(!L){var r=t.innerMode(v,i.htmlState);("xml"==r.mode.name&&null===r.state.tagStart&&!r.state.context&&r.state.tokenize.isInText||i.md_inside&&e.current().indexOf(">")>-1)&&(i.f=f,i.block=h,i.htmlState=null)}return n}function g(t,e){var n=e.listStack[e.listStack.length-1]||0,r=e.indentation=t.quote?e.push(T.formatting+"-"+t.formatting[n]+"-"+t.quote):e.push("error"))}if(t.taskOpen)return e.push("meta"),e.length?e.join(" "):null;if(t.taskClosed)return e.push("property"),e.length?e.join(" "):null;if(t.linkHref?e.push(T.linkHref,"url"):(t.strong&&e.push(T.strong),t.em&&e.push(T.em),t.strikethrough&&e.push(T.strikethrough),t.emoji&&e.push(T.emoji),t.linkText&&e.push(T.linkText),t.code&&e.push(T.code),t.image&&e.push(T.image),t.imageAltText&&e.push(T.imageAltText,"link"),t.imageMarker&&e.push(T.imageMarker)),t.header&&e.push(T.header,T.header+"-"+t.header),t.quote&&(e.push(T.quote),!i.maxBlockquoteDepth||i.maxBlockquoteDepth>=t.quote?e.push(T.quote+"-"+t.quote):e.push(T.quote+"-"+i.maxBlockquoteDepth)),!1!==t.list){var r=(t.listStack.length-1)%3;r?1===r?e.push(T.list2):e.push(T.list3):e.push(T.list1)}return t.trailingSpaceNewLine?e.push("trailing-space-new-line"):t.trailingSpace&&e.push("trailing-space-"+(t.trailingSpace%2?"a":"b")),e.length?e.join(" "):null}function u(t,e){if(t.match(j,!0))return m(e)}function f(e,n){var r=n.text(e,n);if(void 0!==r)return r;if(n.list)return n.list=null,m(n);if(n.taskList)return"x"!==e.match(b,!0)[1]?n.taskOpen=!0:n.taskClosed=!0,i.highlightFormatting&&(n.formatting="task"),n.taskList=!1,m(n);if(n.taskOpen=!1,n.taskClosed=!1,n.header&&e.match(/^#+$/,!0))return i.highlightFormatting&&(n.formatting="header"),m(n);var l=e.next();if(n.linkTitle){n.linkTitle=!1;var o=l;"("===l&&(o=")");var h="^\\s*(?:[^"+(o=(o+"").replace(/([.?*+^\[\]\\(){}|-])/g,"\\$1"))+"\\\\]+|\\\\\\\\|\\\\.)"+o;if(e.match(new RegExp(h),!0))return T.linkHref}if("`"===l){var g=n.formatting;i.highlightFormatting&&(n.formatting="code"),e.eatWhile("`");var u=e.current().length;if(0!=n.code||n.quote&&1!=u){if(u==n.code){y=m(n);return n.code=0,y}return n.formatting=g,m(n)}return n.code=u,m(n)}if(n.code)return m(n);if("\\"===l&&(e.next(),i.highlightFormatting)){var k=m(n),p=T.formatting+"-escape";return k?k+" "+p:p}if("!"===l&&e.match(/\[[^\]]*\] ?(?:\(|\[)/,!1))return n.imageMarker=!0,n.image=!0,i.highlightFormatting&&(n.formatting="image"),m(n);if("["===l&&n.imageMarker&&e.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/,!1))return n.imageMarker=!1,n.imageAltText=!0,i.highlightFormatting&&(n.formatting="image"),m(n);if("]"===l&&n.imageAltText){i.highlightFormatting&&(n.formatting="image");k=m(n);return n.imageAltText=!1,n.image=!1,n.inline=n.f=d,k}if("["===l&&!n.image)return n.linkText=!0,i.highlightFormatting&&(n.formatting="link"),m(n);if("]"===l&&n.linkText){i.highlightFormatting&&(n.formatting="link");k=m(n);return n.linkText=!1,n.inline=n.f=e.match(/\(.*?\)| ?\[.*?\]/,!1)?d:f,k}if("<"===l&&e.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/,!1))return n.f=n.inline=c,i.highlightFormatting&&(n.formatting="link"),(k=m(n))?k+=" ":k="",k+T.linkInline;if("<"===l&&e.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/,!1))return n.f=n.inline=c,i.highlightFormatting&&(n.formatting="link"),(k=m(n))?k+=" ":k="",k+T.linkEmail;if(i.xml&&"<"===l&&e.match(/^(!--|[a-z]+(?:\s+[a-z_:.\-]+(?:\s*=\s*[^ >]+)?)*\s*>)/i,!1)){var x=e.string.indexOf(">",e.pos);if(-1!=x){var S=e.string.substring(e.start,x);/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(S)&&(n.md_inside=!0)}return e.backUp(1),n.htmlState=t.startState(v),a(e,n,s)}if(i.xml&&"<"===l&&e.match(/^\/\w*?>/))return n.md_inside=!1,"tag";if("*"===l||"_"===l){for(var L=1,q=1==e.pos?" ":e.string.charAt(e.pos-2);L<3&&e.eat(l);)L++;var F=e.peek()||" ",M=!/\s/.test(F)&&(!B.test(F)||/\s/.test(q)||B.test(q)),E=!/\s/.test(q)&&(!B.test(q)||/\s/.test(F)||B.test(F)),w=null,j=null;if(L%2&&(n.em||!M||"*"!==l&&E&&!B.test(q)?n.em!=l||!E||"*"!==l&&M&&!B.test(F)||(w=!1):w=!0),L>1&&(n.strong||!M||"*"!==l&&E&&!B.test(q)?n.strong!=l||!E||"*"!==l&&M&&!B.test(F)||(j=!1):j=!0),null!=j||null!=w){i.highlightFormatting&&(n.formatting=null==w?"strong":null==j?"em":"strong em"),!0===w&&(n.em=l),!0===j&&(n.strong=l);y=m(n);return!1===w&&(n.em=!1),!1===j&&(n.strong=!1),y}}else if(" "===l&&(e.eat("*")||e.eat("_"))){if(" "===e.peek())return m(n);e.backUp(1)}if(i.strikethrough)if("~"===l&&e.eatWhile(l)){if(n.strikethrough){i.highlightFormatting&&(n.formatting="strikethrough");var y=m(n);return n.strikethrough=!1,y}if(e.match(/^[^\s]/,!1))return n.strikethrough=!0,i.highlightFormatting&&(n.formatting="strikethrough"),m(n)}else if(" "===l&&e.match(/^~~/,!0)){if(" "===e.peek())return m(n);e.backUp(2)}if(i.emoji&&":"===l&&e.match(/^[a-z_\d+-]+:/)){n.emoji=!0,i.highlightFormatting&&(n.formatting="emoji");var C=m(n);return n.emoji=!1,C}return" "===l&&(e.match(/ +$/,!1)?n.trailingSpace++:n.trailingSpace&&(n.trailingSpaceNewLine=!0)),m(n)}function c(t,e){if(">"===t.next()){e.f=e.inline=f,i.highlightFormatting&&(e.formatting="link");var n=m(e);return n?n+=" ":n="",n+T.linkInline}return t.match(/^[^>]+/,!0),T.linkInline}function d(t,e){if(t.eatSpace())return null;var n=t.next();return"("===n||"["===n?(e.f=e.inline=k("("===n?")":"]"),i.highlightFormatting&&(e.formatting="link-string"),e.linkHref=!0,m(e)):"error"}function k(t){return function(e,n){if(e.next()===t){n.f=n.inline=f,i.highlightFormatting&&(n.formatting="link-string");var r=m(n);return n.linkHref=!1,r}return e.match(H[t]),n.linkHref=!0,m(n)}}function p(t,e){return t.match(/^([^\]\\]|\\.)*\]:/,!1)?(e.f=x,t.next(),i.highlightFormatting&&(e.formatting="link"),e.linkText=!0,m(e)):r(t,e,f)}function x(t,e){if(t.match(/^\]:/,!0)){e.f=e.inline=S,i.highlightFormatting&&(e.formatting="link");var n=m(e);return e.linkText=!1,n}return t.match(/^([^\]\\]|\\.)+/,!0),T.linkText}function S(t,e){return t.eatSpace()?null:(t.match(/^[^\s]+/,!0),void 0===t.peek()?e.linkTitle=!0:t.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/,!0),e.f=e.inline=f,T.linkHref+" url")}var v=t.getMode(e,"text/html"),L="null"==v.name;void 0===i.highlightFormatting&&(i.highlightFormatting=!1),void 0===i.maxBlockquoteDepth&&(i.maxBlockquoteDepth=0),void 0===i.taskLists&&(i.taskLists=!1),void 0===i.strikethrough&&(i.strikethrough=!1),void 0===i.emoji&&(i.emoji=!1),void 0===i.fencedCodeBlockHighlighting&&(i.fencedCodeBlockHighlighting=!0),void 0===i.xml&&(i.xml=!0),void 0===i.tokenTypeOverrides&&(i.tokenTypeOverrides={});var T={header:"header",code:"comment",quote:"quote",list1:"variable-2",list2:"variable-3",list3:"keyword",hr:"hr",image:"image",imageAltText:"image-alt-text",imageMarker:"image-marker",formatting:"formatting",linkInline:"link",linkEmail:"link",linkText:"link",linkHref:"string",em:"em",strong:"strong",strikethrough:"strikethrough",emoji:"builtin"};for(var q in T)T.hasOwnProperty(q)&&i.tokenTypeOverrides[q]&&(T[q]=i.tokenTypeOverrides[q]);var F=/^([*\-_])(?:\s*\1){2,}\s*$/,M=/^(?:[*\-+]|^[0-9]+([.)]))\s+/,b=/^\[(x| )\](?=\s)/,E=i.allowAtxHeaderWithoutSpace?/^(#+)/:/^(#+)(?: |$)/,w=/^ *(?:\={1,}|-{1,})\s*$/,j=/^[^#!\[\]*_\\<>` "'(~:]+/,y=/^(~~~+|```+)[ \t]*([\w+#-]*)[^\n`]*$/,C=/^\s*\[[^\]]+?\]:\s*\S+(\s*\S*\s*)?$/,B=/[!\"#$%&\'()*+,\-\.\/:;<=>?@\[\\\]^_`{|}~—]/,H={")":/^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,"]":/^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\]]|\\.)*\])*?(?=\])/},D={startState:function(){return{f:h,prevLine:{stream:null},thisLine:{stream:null},block:h,htmlState:null,indentation:0,inline:f,text:u,formatting:!1,linkText:!1,linkHref:!1,linkTitle:!1,code:0,em:!1,strong:!1,header:0,setext:0,hr:!1,taskList:!1,list:!1,listStack:[],quote:0,trailingSpace:0,trailingSpaceNewLine:!1,strikethrough:!1,emoji:!1,fencedEndRE:null}},copyState:function(e){return{f:e.f,prevLine:e.prevLine,thisLine:e.thisLine,block:e.block,htmlState:e.htmlState&&t.copyState(v,e.htmlState),indentation:e.indentation,localMode:e.localMode,localState:e.localMode?t.copyState(e.localMode,e.localState):null,inline:e.inline,text:e.text,formatting:!1,linkText:e.linkText,linkTitle:e.linkTitle,code:e.code,em:e.em,strong:e.strong,strikethrough:e.strikethrough,emoji:e.emoji,header:e.header,setext:e.setext,hr:e.hr,taskList:e.taskList,list:e.list,listStack:e.listStack.slice(0),quote:e.quote,indentedCode:e.indentedCode,trailingSpace:e.trailingSpace,trailingSpaceNewLine:e.trailingSpaceNewLine,md_inside:e.md_inside,fencedEndRE:e.fencedEndRE}},token:function(t,e){if(e.formatting=!1,t!=e.thisLine.stream){if(e.header=0,e.hr=!1,t.match(/^\s*$/,!0))return o(e),null;if(e.prevLine=e.thisLine,e.thisLine={stream:t},e.taskList=!1,e.trailingSpace=0,e.trailingSpaceNewLine=!1,e.f=e.block,e.f!=s){var i=t.match(/^\s*/,!0)[0].replace(/\t/g," ").length;if(e.indentation=i,e.indentationDiff=null,i>0)return null}}return e.f(t,e)},innerMode:function(t){return t.block==s?{state:t.htmlState,mode:v}:t.localState?{state:t.localState,mode:t.localMode}:{state:t,mode:D}},indent:function(e,i,n){return e.block==s?v.indent(e.htmlState,i,n):e.localState?e.localMode.indent(e.localState,i,n):t.Pass},blankLine:o,getType:m,closeBrackets:"()[]{}''\"\"``",fold:"markdown"};return D},"xml"),t.defineMIME("text/x-markdown","markdown")}); -------------------------------------------------------------------------------- /static/lib/highlight.pack.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ 2 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){s+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("r",function(e){var r="([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*";return{c:[e.HCM,{b:r,l:r,k:{keyword:"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},r:0},{cN:"number",b:"0[xX][0-9a-fA-F]+[Li]?\\b",r:0},{cN:"number",b:"\\d+(?:[eE][+\\-]?\\d*)?L\\b",r:0},{cN:"number",b:"\\d+\\.(?!\\d)(?:i\\b)?",r:0},{cN:"number",b:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{cN:"number",b:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{b:"`",e:"`",r:0},{cN:"string",c:[e.BE],v:[{b:'"',e:'"'},{b:"'",e:"'"}]}]}});hljs.registerLanguage("python",function(e){var r={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},b={cN:"meta",b:/^(>>>|\.\.\.) /},c={cN:"subst",b:/\{/,e:/\}/,k:r,i:/#/},a={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[b],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[b],r:10},{b:/(fr|rf|f)'''/,e:/'''/,c:[b,c]},{b:/(fr|rf|f)"""/,e:/"""/,c:[b,c]},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},{b:/(fr|rf|f)'/,e:/'/,c:[c]},{b:/(fr|rf|f)"/,e:/"/,c:[c]},e.ASM,e.QSM]},s={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},i={cN:"params",b:/\(/,e:/\)/,c:["self",b,s,a]};return c.c=[a,s,b],{aliases:["py","gyp"],k:r,i:/(<\/|->|\?)|=>/,c:[b,s,a,e.HCM,{v:[{cN:"function",bK:"def"},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,i,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"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 autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}}); -------------------------------------------------------------------------------- /static/lib/marked.min.js: -------------------------------------------------------------------------------- 1 | // https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.12/marked.min.js 2 | (function(){"use strict";var e={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:u,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:u,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:u,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};function t(t){this.tokens=[],this.tokens.links={},this.options=t||g.defaults,this.rules=e.normal,this.options.gfm&&(this.options.tables?this.rules=e.tables:this.rules=e.gfm)}e.bullet=/(?:[*+-]|\d+\.)/,e.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,e.item=o(e.item,"gm")(/bull/g,e.bullet)(),e.list=o(e.list)(/bull/g,e.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+e.def.source+")")(),e.blockquote=o(e.blockquote)("def",e.def)(),e._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b",e.html=o(e.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,e._tag)(),e.paragraph=o(e.paragraph)("hr",e.hr)("heading",e.heading)("lheading",e.lheading)("blockquote",e.blockquote)("tag","<"+e._tag)("def",e.def)(),e.normal=c({},e),e.gfm=c({},e.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),e.gfm.paragraph=o(e.paragraph)("(?!","(?!"+e.gfm.fences.source.replace("\\1","\\2")+"|"+e.list.source.replace("\\1","\\3")+"|")(),e.tables=c({},e.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),t.rules=e,t.lex=function(e,n){return new t(n).lex(e)},t.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},t.prototype.token=function(t,n,s){var r,i,l,o,h,a,p,u,c;for(t=t.replace(/^ +$/gm,"");t;)if((l=this.rules.newline.exec(t))&&(t=t.substring(l[0].length),l[0].length>1&&this.tokens.push({type:"space"})),l=this.rules.code.exec(t))t=t.substring(l[0].length),l=l[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?l:l.replace(/\n+$/,"")});else if(l=this.rules.fences.exec(t))t=t.substring(l[0].length),this.tokens.push({type:"code",lang:l[2],text:l[3]||""});else if(l=this.rules.heading.exec(t))t=t.substring(l[0].length),this.tokens.push({type:"heading",depth:l[1].length,text:l[2]});else if(n&&(l=this.rules.nptable.exec(t))){for(t=t.substring(l[0].length),a={type:"table",header:l[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:l[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:l[3].replace(/\n$/,"").split("\n")},u=0;u ?/gm,""),this.token(l,n,!0),this.tokens.push({type:"blockquote_end"});else if(l=this.rules.list.exec(t)){for(t=t.substring(l[0].length),o=l[2],this.tokens.push({type:"list_start",ordered:o.length>1}),r=!1,c=(l=l[0].match(this.rules.item)).length,u=0;u1&&h.length>1||(t=l.slice(u+1).join("\n")+t,u=c-1)),i=r||/\n\n(?!\s*$)/.test(a),u!==c-1&&(r="\n"===a.charAt(a.length-1),i||(i=r)),this.tokens.push({type:i?"loose_item_start":"list_item_start"}),this.token(a,!1,s),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(l=this.rules.html.exec(t))t=t.substring(l[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&("pre"===l[1]||"script"===l[1]||"style"===l[1]),text:l[0]});else if(!s&&n&&(l=this.rules.def.exec(t)))t=t.substring(l[0].length),this.tokens.links[l[1].toLowerCase()]={href:l[2],title:l[3]};else if(n&&(l=this.rules.table.exec(t))){for(t=t.substring(l[0].length),a={type:"table",header:l[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:l[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:l[3].replace(/(?: *\| *)?\n$/,"").split("\n")},u=0;u])/,autolink:/^<([^ <>]+(@|:\/)[^ <>]+)>/,url:u,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^<'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)([\s\S]*?[^`])\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:u,text:/^[\s\S]+?(?=[\\/g,">").replace(/"/g,""").replace(/'/g,"'")}function o(e,t){return e=e.source,t=t||"",function n(s,r){return s?(r=(r=r.source||r).replace(/(^|[^\[])\^/g,"$1"),e=e.replace(s,r),n):new RegExp(e,t)}}function h(e,t){return a[" "+e]||(/^[^:]+:\/*[^/]*$/.test(e)?a[" "+e]=e+"/":a[" "+e]=e.replace(/[^/]*$/,"")),e=a[" "+e],"//"===t.slice(0,2)?e.replace(/:[\s\S]*/,":")+t:"/"===t.charAt(0)?e.replace(/(:\/*[^/]*)[\s\S]*/,"$1")+t:e+t}n._inside=/(?:\[[^\]]*\]|\\[\[\]]|[^\[\]]|\](?=[^\[]*\]))*/,n._href=/\s*?(?:\s+['"]([\s\S]*?)['"])?\s*/,n.link=o(n.link)("inside",n._inside)("href",n._href)(),n.reflink=o(n.reflink)("inside",n._inside)(),n.normal=c({},n),n.pedantic=c({},n.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/}),n.gfm=c({},n.normal,{escape:o(n.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:o(n.text)("]|","~]|")("|","|https?://|")()}),n.breaks=c({},n.gfm,{br:o(n.br)("{2,}","*")(),text:o(n.gfm.text)("{2,}","*")()}),s.rules=n,s.output=function(e,t,n){return new s(t,n).output(e)},s.prototype.output=function(e){for(var t,n,s,r,i="";e;)if(r=this.rules.escape.exec(e))e=e.substring(r[0].length),i+=r[1];else if(r=this.rules.autolink.exec(e))e=e.substring(r[0].length),"@"===r[2]?(n=l(":"===r[1].charAt(6)?this.mangle(r[1].substring(7)):this.mangle(r[1])),s=this.mangle("mailto:")+n):s=n=l(r[1]),i+=this.renderer.link(s,null,n);else if(this.inLink||!(r=this.rules.url.exec(e))){if(r=this.rules.tag.exec(e))!this.inLink&&/^/i.test(r[0])&&(this.inLink=!1),e=e.substring(r[0].length),i+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(r[0]):l(r[0]):r[0];else if(r=this.rules.link.exec(e))e=e.substring(r[0].length),this.inLink=!0,i+=this.outputLink(r,{href:r[2],title:r[3]}),this.inLink=!1;else if((r=this.rules.reflink.exec(e))||(r=this.rules.nolink.exec(e))){if(e=e.substring(r[0].length),t=(r[2]||r[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){i+=r[0].charAt(0),e=r[0].substring(1)+e;continue}this.inLink=!0,i+=this.outputLink(r,t),this.inLink=!1}else if(r=this.rules.strong.exec(e))e=e.substring(r[0].length),i+=this.renderer.strong(this.output(r[2]||r[1]));else if(r=this.rules.em.exec(e))e=e.substring(r[0].length),i+=this.renderer.em(this.output(r[2]||r[1]));else if(r=this.rules.code.exec(e))e=e.substring(r[0].length),i+=this.renderer.codespan(l(r[2].trim(),!0));else if(r=this.rules.br.exec(e))e=e.substring(r[0].length),i+=this.renderer.br();else if(r=this.rules.del.exec(e))e=e.substring(r[0].length),i+=this.renderer.del(this.output(r[1]));else if(r=this.rules.text.exec(e))e=e.substring(r[0].length),i+=this.renderer.text(l(this.smartypants(r[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else e=e.substring(r[0].length),s=n=l(r[1]),i+=this.renderer.link(s,null,n);return i},s.prototype.outputLink=function(e,t){var n=l(t.href),s=t.title?l(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,s,this.output(e[1])):this.renderer.image(n,s,l(e[1]))},s.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},s.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",s=e.length,r=0;r.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},r.prototype.code=function(e,t,n){if(this.options.highlight){var s=this.options.highlight(e,t);null!=s&&s!==e&&(n=!0,e=s)}return t?'
'+(n?e:l(e,!0))+"\n
\n":"
"+(n?e:l(e,!0))+"\n
"},r.prototype.blockquote=function(e){return"
\n"+e+"
\n"},r.prototype.html=function(e){return e},r.prototype.heading=function(e,t,n){return"'+e+"\n"},r.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},r.prototype.list=function(e,t){var n=t?"ol":"ul";return"<"+n+">\n"+e+"\n"},r.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},r.prototype.paragraph=function(e){return"

    "+e+"

    \n"},r.prototype.table=function(e,t){return"\n\n"+e+"\n\n"+t+"\n
    \n"},r.prototype.tablerow=function(e){return"\n"+e+"\n"},r.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' style="text-align:'+t.align+'">':"<"+n+">")+e+"\n"},r.prototype.strong=function(e){return""+e+""},r.prototype.em=function(e){return""+e+""},r.prototype.codespan=function(e){return""+e+""},r.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},r.prototype.del=function(e){return""+e+""},r.prototype.link=function(e,t,n){if(this.options.sanitize){try{var s=decodeURIComponent((r=e,r.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi,function(e,t){return"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""}))).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return n}if(0===s.indexOf("javascript:")||0===s.indexOf("vbscript:")||0===s.indexOf("data:"))return n}var r;this.options.baseUrl&&!p.test(e)&&(e=h(this.options.baseUrl,e));var i='
    "},r.prototype.image=function(e,t,n){this.options.baseUrl&&!p.test(e)&&(e=h(this.options.baseUrl,e));var s=''+n+'":">"},r.prototype.text=function(e){return e},i.parse=function(e,t,n){return new i(t,n).parse(e)},i.prototype.parse=function(e){this.inline=new s(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},i.prototype.next=function(){return this.token=this.tokens.pop()},i.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},i.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},i.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,s,r="",i="";for(n="",e=0;eAn error occurred:

    "+l(e.message+"",!0)+"
    ";throw e}}u.exec=u,g.options=g.setOptions=function(e){return c(g.defaults,e),g},g.defaults={gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!1,sanitizer:null,mangle:!0,smartLists:!1,silent:!1,highlight:null,langPrefix:"lang-",smartypants:!1,headerPrefix:"",renderer:new r,xhtml:!1,baseUrl:null},g.Parser=i,g.parser=i.parse,g.Renderer=r,g.Lexer=t,g.lexer=t.lex,g.InlineLexer=s,g.inlineLexer=s.output,g.parse=g,"undefined"!=typeof module&&"object"==typeof exports?module.exports=g:"function"==typeof define&&define.amd?define(function(){return g}):this.marked=g}).call(function(){return this||("undefined"!=typeof window?window:global)}()); -------------------------------------------------------------------------------- /static/lib/vega-embed.min.js: -------------------------------------------------------------------------------- 1 | // https://cdnjs.cloudflare.com/ajax/libs/vega-embed/3.0.0-rc7/vega-embed.min.js 2 | 3 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).vegaEmbed=e()}}(function(){return function e(t,n,r){function i(u,a){if(!n[u]){if(!t[u]){var s="function"==typeof require&&require;if(!a&&s)return s(u,!0);if(o)return o(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[u]={exports:{}};t[u][0].call(l.exports,function(e){var n=t[u][1][e];return i(n||e)},l,l.exports,e,t,n,r)}return n[u].exports}for(var o="function"==typeof require&&require,u=0;ul)return 1;if(l>c)return-1}if([u[2],a[2]].every(i.test.bind(i))){var f=i.exec(u[2])[1].split(".").map(t),h=i.exec(a[2])[1].split(".").map(t);for(s=0;sh[s])return 1;if(h[s]>f[s])return-1}}else if([u[2],a[2]].some(i.test.bind(i)))return i.test(u[2])?-1:1;return 0}})},{}],2:[function(e,t,n){!function(e,r){r("object"==typeof n&&void 0!==t?n:e.d3=e.d3||{})}(this,function(e){"use strict";function t(e){return function(){var t=this.ownerDocument,n=this.namespaceURI;return n===K&&t.documentElement.namespaceURI===K?t.createElement(e):t.createElementNS(n,e)}}function n(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function r(){return new i}function i(){this._="@"+(++ne).toString(36)}function o(e,t,n){return e=u(e,t,n),function(t){var n=t.relatedTarget;n&&(n===this||8&n.compareDocumentPosition(this))||e.call(this,t)}}function u(t,n,r){return function(i){var o=e.event;e.event=i;try{t.call(this,this.__data__,n,r)}finally{e.event=o}}}function a(e){return e.trim().split(/^|\s+/).map(function(e){var t="",n=e.indexOf(".");return n>=0&&(t=e.slice(n+1),e=e.slice(0,n)),{type:e,name:t}})}function s(e){return function(){var t=this.__on;if(t){for(var n,r=0,i=-1,o=t.length;rt?1:e>=t?0:NaN}function g(e){return function(){this.removeAttribute(e)}}function m(e){return function(){this.removeAttributeNS(e.space,e.local)}}function y(e,t){return function(){this.setAttribute(e,t)}}function _(e,t){return function(){this.setAttributeNS(e.space,e.local,t)}}function w(e,t){return function(){var n=t.apply(this,arguments);null==n?this.removeAttribute(e):this.setAttribute(e,n)}}function b(e,t){return function(){var n=t.apply(this,arguments);null==n?this.removeAttributeNS(e.space,e.local):this.setAttributeNS(e.space,e.local,n)}}function x(e){return function(){this.style.removeProperty(e)}}function A(e,t,n){return function(){this.style.setProperty(e,t,n)}}function S(e,t,n){return function(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(e):this.style.setProperty(e,r,n)}}function E(e,t){return e.style.getPropertyValue(t)||ve(e).getComputedStyle(e,null).getPropertyValue(t)}function N(e){return function(){delete this[e]}}function P(e,t){return function(){this[e]=t}}function O(e,t){return function(){var n=t.apply(this,arguments);null==n?delete this[e]:this[e]=n}}function L(e){return e.trim().split(/^|\s+/)}function M(e){return e.classList||new T(e)}function T(e){this._node=e,this._names=L(e.getAttribute("class")||"")}function j(e,t){for(var n=M(e),r=-1,i=t.length;++r=0&&"xmlns"!==(t=e.slice(0,n))&&(e=e.slice(n+1)),Q.hasOwnProperty(t)?{space:Q[t],local:e}:e},te=function(e){var r=ee(e);return(r.local?n:t)(r)},ne=0;i.prototype=r.prototype={constructor:i,get:function(e){for(var t=this._;!(t in e);)if(!(e=e.parentNode))return;return e[t]},set:function(e,t){return e[this._]=t},remove:function(e){return this._ in e&&delete e[this._]},toString:function(){return this._}};var re=function(e){return function(){return this.matches(e)}};if("undefined"!=typeof document){var ie=document.documentElement;if(!ie.matches){var oe=ie.webkitMatchesSelector||ie.msMatchesSelector||ie.mozMatchesSelector||ie.oMatchesSelector;re=function(e){return function(){return oe.call(this,e)}}}}var ue=re,ae={};e.event=null,"undefined"!=typeof document&&("onmouseenter"in document.documentElement||(ae={mouseenter:"mouseover",mouseleave:"mouseout"}));var se=function(){for(var t,n=e.event;t=n.sourceEvent;)n=t;return n},ce=function(e,t){var n=e.ownerSVGElement||e;if(n.createSVGPoint){var r=n.createSVGPoint();return r.x=t.clientX,r.y=t.clientY,r=r.matrixTransform(e.getScreenCTM().inverse()),[r.x,r.y]}var i=e.getBoundingClientRect();return[t.clientX-i.left-e.clientLeft,t.clientY-i.top-e.clientTop]},le=function(e){return null==e?l:function(){return this.querySelector(e)}},fe=function(e){return null==e?f:function(){return this.querySelectorAll(e)}},he=function(e){return new Array(e.length)};h.prototype={constructor:h,appendChild:function(e){return this._parent.insertBefore(e,this._next)},insertBefore:function(e,t){return this._parent.insertBefore(e,t)},querySelector:function(e){return this._parent.querySelector(e)},querySelectorAll:function(e){return this._parent.querySelectorAll(e)}};var pe=function(e){return function(){return e}},de="$",ve=function(e){return e.ownerDocument&&e.ownerDocument.defaultView||e.document&&e||e.defaultView};T.prototype={add:function(e){this._names.indexOf(e)<0&&(this._names.push(e),this._node.setAttribute("class",this._names.join(" ")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}};var ge=[null];W.prototype=Z.prototype={constructor:W,select:function(e){"function"!=typeof e&&(e=le(e));for(var t=this._groups,n=t.length,r=new Array(n),i=0;i=x&&(x=b+1);!(w=y[x])&&++x=0;)(r=i[o])&&(u&&u!==r.nextSibling&&u.parentNode.insertBefore(r,u),u=r);return this},sort:function(e){e||(e=v);for(var t=this._groups,n=t.length,r=new Array(n),i=0;i1?this.each((null==t?x:"function"==typeof t?S:A)(e,t,null==n?"":n)):E(this.node(),e)},property:function(e,t){return arguments.length>1?this.each((null==t?N:"function"==typeof t?O:P)(e,t)):this.node()[e]},classed:function(e,t){var n=L(e+"");if(arguments.length<2){for(var r=M(this.node()),i=-1,o=n.length;++i0&&console.warn("The input spec uses "+y+" "+_.version+", but the current version of "+f[y]+" is "+h[y]+".")):y=a.mode||"vega";var w=p[y](t);"vega-lite"===y&&w.$schema&&(_=c.default(w.$schema),o(_.version,h.vega)>0&&console.warn("The compiled spec uses Vega "+_.version+", but current version is "+h.vega+"."));var b=u.select(e).classed("vega-embed",!0).html("");a.onBeforeParse&&(w=a.onBeforeParse(w));var x=n.vega.parse(w,a.config),A=new n.vega.View(x,{loader:d,logLevel:g,renderer:v}).initialize(e);if("vega-lite"!==y&&A.hover(),a&&(a.width&&A.width(a.width),a.height&&A.height(a.height),a.padding&&A.padding(a.padding)),A.run(),!1!==s){var S=b.append("div").attr("class","vega-actions");if(!0===s||!1!==s.export){var E="canvas"===v?"png":"svg";S.append("a").text("Export as "+E.toUpperCase()).attr("href","#").attr("target","_blank").attr("download",(t.name||"vega")+"."+E).on("mousedown",function(){var e=this;A.toImageURL(E).then(function(t){e.href=t}).catch(function(e){throw e}),u.event.preventDefault()})}if(!0!==s&&!1===s.source||S.append("a").text("View Source").attr("href","#").on("click",function(){i(JSON.stringify(t,null,2),a.sourceHeader||"",a.sourceFooter||""),u.event.preventDefault()}),!0===s||!1!==s.editor){var N=a.editorUrl||"https://vega.github.io/editor/";S.append("a").text("Open in Vega Editor").attr("href","#").on("click",function(){l.post(window,N,{mode:y,spec:JSON.stringify(t,null,2)}),u.event.preventDefault()})}}return Promise.resolve({view:A,spec:t})}catch(e){return Promise.reject(e)}}function i(e,t,n){var r=""+t+"' + '
    ",i="
    "+n+"",o=window.open("");o.document.write(r+e+i),o.document.title="Vega JSON Source"}Object.defineProperty(n,"__esModule",{value:!0});var o=e("compare-versions"),u=e("d3-selection"),a="undefined"!=typeof window?window.vega:void 0!==t?t.vega:null,s="undefined"!=typeof window?window.vl:void 0!==t?t.vl:null,c=e("vega-schema-url-parser");n.vega=a,n.vl=s;var l=e("./post"),f={vega:"Vega","vega-lite":"Vega-Lite"},h={vega:n.vega.version,"vega-lite":n.vl?n.vl.version:"not available"},p={vega:function(e){return e},"vega-lite":function(e){return n.vl.compile(e).spec}};n.default=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./post":6,"compare-versions":1,"d3-selection":2,"vega-schema-url-parser":3}],5:[function(e,t,n){(function(n){"use strict";var r="undefined"!=typeof window?window.vega:void 0!==n?n.vega:null,i="undefined"!=typeof window?window.vl:void 0!==n?n.vl:null,o=e("./embed"),u=o.default;u.default=o.default,u.vega=r,u.vl=i,t.exports=u}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./embed":4}],6:[function(e,t,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.post=function(e,t,n){function r(t){t.source===o&&(a=0,e.removeEventListener("message",r,!1))}function i(){a<=0||(o.postMessage(n,"*"),setTimeout(i,u),a-=1)}var o=e.open(t),u=250,a=~~(1e4/u);e.addEventListener("message",r,!1),setTimeout(i,u)}},{}]},{},[5])(5)}); -------------------------------------------------------------------------------- /static/lib/markdown.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: http://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror", "../xml/xml", "../meta"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { 15 | 16 | var htmlMode = CodeMirror.getMode(cmCfg, "text/html"); 17 | var htmlModeMissing = htmlMode.name == "null" 18 | 19 | function getMode(name) { 20 | if (CodeMirror.findModeByName) { 21 | var found = CodeMirror.findModeByName(name); 22 | if (found) name = found.mime || found.mimes[0]; 23 | } 24 | var mode = CodeMirror.getMode(cmCfg, name); 25 | return mode.name == "null" ? null : mode; 26 | } 27 | 28 | // Should characters that affect highlighting be highlighted separate? 29 | // Does not include characters that will be output (such as `1.` and `-` for lists) 30 | if (modeCfg.highlightFormatting === undefined) 31 | modeCfg.highlightFormatting = false; 32 | 33 | // Maximum number of nested blockquotes. Set to 0 for infinite nesting. 34 | // Excess `>` will emit `error` token. 35 | if (modeCfg.maxBlockquoteDepth === undefined) 36 | modeCfg.maxBlockquoteDepth = 0; 37 | 38 | // Should underscores in words open/close em/strong? 39 | if (modeCfg.underscoresBreakWords === undefined) 40 | modeCfg.underscoresBreakWords = true; 41 | 42 | // Use `fencedCodeBlocks` to configure fenced code blocks. false to 43 | // disable, string to specify a precise regexp that the fence should 44 | // match, and true to allow three or more backticks or tildes (as 45 | // per CommonMark). 46 | 47 | // Turn on task lists? ("- [ ] " and "- [x] ") 48 | if (modeCfg.taskLists === undefined) modeCfg.taskLists = false; 49 | 50 | // Turn on strikethrough syntax 51 | if (modeCfg.strikethrough === undefined) 52 | modeCfg.strikethrough = false; 53 | 54 | // Allow token types to be overridden by user-provided token types. 55 | if (modeCfg.tokenTypeOverrides === undefined) 56 | modeCfg.tokenTypeOverrides = {}; 57 | 58 | var tokenTypes = { 59 | header: "header", 60 | code: "comment", 61 | quote: "quote", 62 | list1: "variable-2", 63 | list2: "variable-3", 64 | list3: "keyword", 65 | hr: "hr", 66 | image: "image", 67 | imageAltText: "image-alt-text", 68 | imageMarker: "image-marker", 69 | formatting: "formatting", 70 | linkInline: "link", 71 | linkEmail: "link", 72 | linkText: "link", 73 | linkHref: "string", 74 | em: "em", 75 | strong: "strong", 76 | strikethrough: "strikethrough" 77 | }; 78 | 79 | for (var tokenType in tokenTypes) { 80 | if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) { 81 | tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType]; 82 | } 83 | } 84 | 85 | var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/ 86 | , listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/ 87 | , taskListRE = /^\[(x| )\](?=\s)/ // Must follow listRE 88 | , atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/ 89 | , setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/ 90 | , textRE = /^[^#!\[\]*_\\<>` "'(~]+/ 91 | , fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) + 92 | ")[ \\t]*([\\w+#\-]*)"); 93 | 94 | function switchInline(stream, state, f) { 95 | state.f = state.inline = f; 96 | return f(stream, state); 97 | } 98 | 99 | function switchBlock(stream, state, f) { 100 | state.f = state.block = f; 101 | return f(stream, state); 102 | } 103 | 104 | function lineIsEmpty(line) { 105 | return !line || !/\S/.test(line.string) 106 | } 107 | 108 | // Blocks 109 | 110 | function blankLine(state) { 111 | // Reset linkTitle state 112 | state.linkTitle = false; 113 | // Reset EM state 114 | state.em = false; 115 | // Reset STRONG state 116 | state.strong = false; 117 | // Reset strikethrough state 118 | state.strikethrough = false; 119 | // Reset state.quote 120 | state.quote = 0; 121 | // Reset state.indentedCode 122 | state.indentedCode = false; 123 | if (htmlModeMissing && state.f == htmlBlock) { 124 | state.f = inlineNormal; 125 | state.block = blockNormal; 126 | } 127 | // Reset state.trailingSpace 128 | state.trailingSpace = 0; 129 | state.trailingSpaceNewLine = false; 130 | // Mark this line as blank 131 | state.prevLine = state.thisLine 132 | state.thisLine = null 133 | return null; 134 | } 135 | 136 | function blockNormal(stream, state) { 137 | 138 | var sol = stream.sol(); 139 | 140 | var prevLineIsList = state.list !== false, 141 | prevLineIsIndentedCode = state.indentedCode; 142 | 143 | state.indentedCode = false; 144 | 145 | if (prevLineIsList) { 146 | if (state.indentationDiff >= 0) { // Continued list 147 | if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block 148 | state.indentation -= state.indentationDiff; 149 | } 150 | state.list = null; 151 | } else if (state.indentation > 0) { 152 | state.list = null; 153 | } else { // No longer a list 154 | state.list = false; 155 | } 156 | } 157 | 158 | var match = null; 159 | if (state.indentationDiff >= 4) { 160 | stream.skipToEnd(); 161 | if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) { 162 | state.indentation -= 4; 163 | state.indentedCode = true; 164 | return tokenTypes.code; 165 | } else { 166 | return null; 167 | } 168 | } else if (stream.eatSpace()) { 169 | return null; 170 | } else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) { 171 | state.header = match[1].length; 172 | if (modeCfg.highlightFormatting) state.formatting = "header"; 173 | state.f = state.inline; 174 | return getType(state); 175 | } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList && 176 | !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) { 177 | state.header = match[0].charAt(0) == '=' ? 1 : 2; 178 | if (modeCfg.highlightFormatting) state.formatting = "header"; 179 | state.f = state.inline; 180 | return getType(state); 181 | } else if (stream.eat('>')) { 182 | state.quote = sol ? 1 : state.quote + 1; 183 | if (modeCfg.highlightFormatting) state.formatting = "quote"; 184 | stream.eatSpace(); 185 | return getType(state); 186 | } else if (stream.peek() === '[') { 187 | return switchInline(stream, state, footnoteLink); 188 | } else if (stream.match(hrRE, true)) { 189 | state.hr = true; 190 | return tokenTypes.hr; 191 | } else if (match = stream.match(listRE)) { 192 | var listType = match[1] ? "ol" : "ul"; 193 | state.indentation = stream.column() + stream.current().length; 194 | state.list = true; 195 | 196 | // While this list item's marker's indentation 197 | // is less than the deepest list item's content's indentation, 198 | // pop the deepest list item indentation off the stack. 199 | while (state.listStack && stream.column() < state.listStack[state.listStack.length - 1]) { 200 | state.listStack.pop(); 201 | } 202 | 203 | // Add this list item's content's indentation to the stack 204 | state.listStack.push(state.indentation); 205 | 206 | if (modeCfg.taskLists && stream.match(taskListRE, false)) { 207 | state.taskList = true; 208 | } 209 | state.f = state.inline; 210 | if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType]; 211 | return getType(state); 212 | } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) { 213 | state.fencedChars = match[1] 214 | // try switching mode 215 | state.localMode = getMode(match[2]); 216 | if (state.localMode) state.localState = CodeMirror.startState(state.localMode); 217 | state.f = state.block = local; 218 | if (modeCfg.highlightFormatting) state.formatting = "code-block"; 219 | state.code = -1 220 | return getType(state); 221 | } 222 | 223 | return switchInline(stream, state, state.inline); 224 | } 225 | 226 | function htmlBlock(stream, state) { 227 | var style = htmlMode.token(stream, state.htmlState); 228 | if (!htmlModeMissing) { 229 | var inner = CodeMirror.innerMode(htmlMode, state.htmlState) 230 | if ((inner.mode.name == "xml" && inner.state.tagStart === null && 231 | (!inner.state.context && inner.state.tokenize.isInText)) || 232 | (state.md_inside && stream.current().indexOf(">") > -1)) { 233 | state.f = inlineNormal; 234 | state.block = blockNormal; 235 | state.htmlState = null; 236 | } 237 | } 238 | return style; 239 | } 240 | 241 | function local(stream, state) { 242 | if (state.fencedChars && stream.match(state.fencedChars, false)) { 243 | state.localMode = state.localState = null; 244 | state.f = state.block = leavingLocal; 245 | return null; 246 | } else if (state.localMode) { 247 | return state.localMode.token(stream, state.localState); 248 | } else { 249 | stream.skipToEnd(); 250 | return tokenTypes.code; 251 | } 252 | } 253 | 254 | function leavingLocal(stream, state) { 255 | stream.match(state.fencedChars); 256 | state.block = blockNormal; 257 | state.f = inlineNormal; 258 | state.fencedChars = null; 259 | if (modeCfg.highlightFormatting) state.formatting = "code-block"; 260 | state.code = 1 261 | var returnType = getType(state); 262 | state.code = 0 263 | return returnType; 264 | } 265 | 266 | // Inline 267 | function getType(state) { 268 | var styles = []; 269 | 270 | if (state.formatting) { 271 | styles.push(tokenTypes.formatting); 272 | 273 | if (typeof state.formatting === "string") state.formatting = [state.formatting]; 274 | 275 | for (var i = 0; i < state.formatting.length; i++) { 276 | styles.push(tokenTypes.formatting + "-" + state.formatting[i]); 277 | 278 | if (state.formatting[i] === "header") { 279 | styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header); 280 | } 281 | 282 | // Add `formatting-quote` and `formatting-quote-#` for blockquotes 283 | // Add `error` instead if the maximum blockquote nesting depth is passed 284 | if (state.formatting[i] === "quote") { 285 | if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { 286 | styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote); 287 | } else { 288 | styles.push("error"); 289 | } 290 | } 291 | } 292 | } 293 | 294 | if (state.taskOpen) { 295 | styles.push("meta"); 296 | return styles.length ? styles.join(' ') : null; 297 | } 298 | if (state.taskClosed) { 299 | styles.push("property"); 300 | return styles.length ? styles.join(' ') : null; 301 | } 302 | 303 | if (state.linkHref) { 304 | styles.push(tokenTypes.linkHref, "url"); 305 | } else { // Only apply inline styles to non-url text 306 | if (state.strong) { styles.push(tokenTypes.strong); } 307 | if (state.em) { styles.push(tokenTypes.em); } 308 | if (state.strikethrough) { styles.push(tokenTypes.strikethrough); } 309 | if (state.linkText) { styles.push(tokenTypes.linkText); } 310 | if (state.code) { styles.push(tokenTypes.code); } 311 | if (state.image) { styles.push(tokenTypes.image); } 312 | if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); } 313 | if (state.imageMarker) { styles.push(tokenTypes.imageMarker); } 314 | } 315 | 316 | if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); } 317 | 318 | if (state.quote) { 319 | styles.push(tokenTypes.quote); 320 | 321 | // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth 322 | if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { 323 | styles.push(tokenTypes.quote + "-" + state.quote); 324 | } else { 325 | styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth); 326 | } 327 | } 328 | 329 | if (state.list !== false) { 330 | var listMod = (state.listStack.length - 1) % 3; 331 | if (!listMod) { 332 | styles.push(tokenTypes.list1); 333 | } else if (listMod === 1) { 334 | styles.push(tokenTypes.list2); 335 | } else { 336 | styles.push(tokenTypes.list3); 337 | } 338 | } 339 | 340 | if (state.trailingSpaceNewLine) { 341 | styles.push("trailing-space-new-line"); 342 | } else if (state.trailingSpace) { 343 | styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b")); 344 | } 345 | 346 | return styles.length ? styles.join(' ') : null; 347 | } 348 | 349 | function handleText(stream, state) { 350 | if (stream.match(textRE, true)) { 351 | return getType(state); 352 | } 353 | return undefined; 354 | } 355 | 356 | function inlineNormal(stream, state) { 357 | var style = state.text(stream, state); 358 | if (typeof style !== 'undefined') 359 | return style; 360 | 361 | if (state.list) { // List marker (*, +, -, 1., etc) 362 | state.list = null; 363 | return getType(state); 364 | } 365 | 366 | if (state.taskList) { 367 | var taskOpen = stream.match(taskListRE, true)[1] !== "x"; 368 | if (taskOpen) state.taskOpen = true; 369 | else state.taskClosed = true; 370 | if (modeCfg.highlightFormatting) state.formatting = "task"; 371 | state.taskList = false; 372 | return getType(state); 373 | } 374 | 375 | state.taskOpen = false; 376 | state.taskClosed = false; 377 | 378 | if (state.header && stream.match(/^#+$/, true)) { 379 | if (modeCfg.highlightFormatting) state.formatting = "header"; 380 | return getType(state); 381 | } 382 | 383 | // Get sol() value now, before character is consumed 384 | var sol = stream.sol(); 385 | 386 | var ch = stream.next(); 387 | 388 | // Matches link titles present on next line 389 | if (state.linkTitle) { 390 | state.linkTitle = false; 391 | var matchCh = ch; 392 | if (ch === '(') { 393 | matchCh = ')'; 394 | } 395 | matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); 396 | var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh; 397 | if (stream.match(new RegExp(regex), true)) { 398 | return tokenTypes.linkHref; 399 | } 400 | } 401 | 402 | // If this block is changed, it may need to be updated in GFM mode 403 | if (ch === '`') { 404 | var previousFormatting = state.formatting; 405 | if (modeCfg.highlightFormatting) state.formatting = "code"; 406 | stream.eatWhile('`'); 407 | var count = stream.current().length 408 | if (state.code == 0) { 409 | state.code = count 410 | return getType(state) 411 | } else if (count == state.code) { // Must be exact 412 | var t = getType(state) 413 | state.code = 0 414 | return t 415 | } else { 416 | state.formatting = previousFormatting 417 | return getType(state) 418 | } 419 | } else if (state.code) { 420 | return getType(state); 421 | } 422 | 423 | if (ch === '\\') { 424 | stream.next(); 425 | if (modeCfg.highlightFormatting) { 426 | var type = getType(state); 427 | var formattingEscape = tokenTypes.formatting + "-escape"; 428 | return type ? type + " " + formattingEscape : formattingEscape; 429 | } 430 | } 431 | 432 | if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) { 433 | state.imageMarker = true; 434 | state.image = true; 435 | if (modeCfg.highlightFormatting) state.formatting = "image"; 436 | return getType(state); 437 | } 438 | 439 | if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) { 440 | state.imageMarker = false; 441 | state.imageAltText = true 442 | if (modeCfg.highlightFormatting) state.formatting = "image"; 443 | return getType(state); 444 | } 445 | 446 | if (ch === ']' && state.imageAltText) { 447 | if (modeCfg.highlightFormatting) state.formatting = "image"; 448 | var type = getType(state); 449 | state.imageAltText = false; 450 | state.image = false; 451 | state.inline = state.f = linkHref; 452 | return type; 453 | } 454 | 455 | if (ch === '[' && stream.match(/[^\]]*\](\(.*\)| ?\[.*?\])/, false) && !state.image) { 456 | state.linkText = true; 457 | if (modeCfg.highlightFormatting) state.formatting = "link"; 458 | return getType(state); 459 | } 460 | 461 | if (ch === ']' && state.linkText && stream.match(/\(.*?\)| ?\[.*?\]/, false)) { 462 | if (modeCfg.highlightFormatting) state.formatting = "link"; 463 | var type = getType(state); 464 | state.linkText = false; 465 | state.inline = state.f = linkHref; 466 | return type; 467 | } 468 | 469 | if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) { 470 | state.f = state.inline = linkInline; 471 | if (modeCfg.highlightFormatting) state.formatting = "link"; 472 | var type = getType(state); 473 | if (type){ 474 | type += " "; 475 | } else { 476 | type = ""; 477 | } 478 | return type + tokenTypes.linkInline; 479 | } 480 | 481 | if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) { 482 | state.f = state.inline = linkInline; 483 | if (modeCfg.highlightFormatting) state.formatting = "link"; 484 | var type = getType(state); 485 | if (type){ 486 | type += " "; 487 | } else { 488 | type = ""; 489 | } 490 | return type + tokenTypes.linkEmail; 491 | } 492 | 493 | if (ch === '<' && stream.match(/^(!--|\w)/, false)) { 494 | var end = stream.string.indexOf(">", stream.pos); 495 | if (end != -1) { 496 | var atts = stream.string.substring(stream.start, end); 497 | if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true; 498 | } 499 | stream.backUp(1); 500 | state.htmlState = CodeMirror.startState(htmlMode); 501 | return switchBlock(stream, state, htmlBlock); 502 | } 503 | 504 | if (ch === '<' && stream.match(/^\/\w*?>/)) { 505 | state.md_inside = false; 506 | return "tag"; 507 | } 508 | 509 | var ignoreUnderscore = false; 510 | if (!modeCfg.underscoresBreakWords) { 511 | if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) { 512 | var prevPos = stream.pos - 2; 513 | if (prevPos >= 0) { 514 | var prevCh = stream.string.charAt(prevPos); 515 | if (prevCh !== '_' && prevCh.match(/(\w)/, false)) { 516 | ignoreUnderscore = true; 517 | } 518 | } 519 | } 520 | } 521 | if (ch === '*' || (ch === '_' && !ignoreUnderscore)) { 522 | if (sol && stream.peek() === ' ') { 523 | // Do nothing, surrounded by newline and space 524 | } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG 525 | if (modeCfg.highlightFormatting) state.formatting = "strong"; 526 | var t = getType(state); 527 | state.strong = false; 528 | return t; 529 | } else if (!state.strong && stream.eat(ch)) { // Add STRONG 530 | state.strong = ch; 531 | if (modeCfg.highlightFormatting) state.formatting = "strong"; 532 | return getType(state); 533 | } else if (state.em === ch) { // Remove EM 534 | if (modeCfg.highlightFormatting) state.formatting = "em"; 535 | var t = getType(state); 536 | state.em = false; 537 | return t; 538 | } else if (!state.em) { // Add EM 539 | state.em = ch; 540 | if (modeCfg.highlightFormatting) state.formatting = "em"; 541 | return getType(state); 542 | } 543 | } else if (ch === ' ') { 544 | if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces 545 | if (stream.peek() === ' ') { // Surrounded by spaces, ignore 546 | return getType(state); 547 | } else { // Not surrounded by spaces, back up pointer 548 | stream.backUp(1); 549 | } 550 | } 551 | } 552 | 553 | if (modeCfg.strikethrough) { 554 | if (ch === '~' && stream.eatWhile(ch)) { 555 | if (state.strikethrough) {// Remove strikethrough 556 | if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; 557 | var t = getType(state); 558 | state.strikethrough = false; 559 | return t; 560 | } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough 561 | state.strikethrough = true; 562 | if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; 563 | return getType(state); 564 | } 565 | } else if (ch === ' ') { 566 | if (stream.match(/^~~/, true)) { // Probably surrounded by space 567 | if (stream.peek() === ' ') { // Surrounded by spaces, ignore 568 | return getType(state); 569 | } else { // Not surrounded by spaces, back up pointer 570 | stream.backUp(2); 571 | } 572 | } 573 | } 574 | } 575 | 576 | if (ch === ' ') { 577 | if (stream.match(/ +$/, false)) { 578 | state.trailingSpace++; 579 | } else if (state.trailingSpace) { 580 | state.trailingSpaceNewLine = true; 581 | } 582 | } 583 | 584 | return getType(state); 585 | } 586 | 587 | function linkInline(stream, state) { 588 | var ch = stream.next(); 589 | 590 | if (ch === ">") { 591 | state.f = state.inline = inlineNormal; 592 | if (modeCfg.highlightFormatting) state.formatting = "link"; 593 | var type = getType(state); 594 | if (type){ 595 | type += " "; 596 | } else { 597 | type = ""; 598 | } 599 | return type + tokenTypes.linkInline; 600 | } 601 | 602 | stream.match(/^[^>]+/, true); 603 | 604 | return tokenTypes.linkInline; 605 | } 606 | 607 | function linkHref(stream, state) { 608 | // Check if space, and return NULL if so (to avoid marking the space) 609 | if(stream.eatSpace()){ 610 | return null; 611 | } 612 | var ch = stream.next(); 613 | if (ch === '(' || ch === '[') { 614 | state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]", 0); 615 | if (modeCfg.highlightFormatting) state.formatting = "link-string"; 616 | state.linkHref = true; 617 | return getType(state); 618 | } 619 | return 'error'; 620 | } 621 | 622 | var linkRE = { 623 | ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/, 624 | "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\\]]|\\.)*\])*?(?=\])/ 625 | } 626 | 627 | function getLinkHrefInside(endChar) { 628 | return function(stream, state) { 629 | var ch = stream.next(); 630 | 631 | if (ch === endChar) { 632 | state.f = state.inline = inlineNormal; 633 | if (modeCfg.highlightFormatting) state.formatting = "link-string"; 634 | var returnState = getType(state); 635 | state.linkHref = false; 636 | return returnState; 637 | } 638 | 639 | stream.match(linkRE[endChar]) 640 | state.linkHref = true; 641 | return getType(state); 642 | }; 643 | } 644 | 645 | function footnoteLink(stream, state) { 646 | if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) { 647 | state.f = footnoteLinkInside; 648 | stream.next(); // Consume [ 649 | if (modeCfg.highlightFormatting) state.formatting = "link"; 650 | state.linkText = true; 651 | return getType(state); 652 | } 653 | return switchInline(stream, state, inlineNormal); 654 | } 655 | 656 | function footnoteLinkInside(stream, state) { 657 | if (stream.match(/^\]:/, true)) { 658 | state.f = state.inline = footnoteUrl; 659 | if (modeCfg.highlightFormatting) state.formatting = "link"; 660 | var returnType = getType(state); 661 | state.linkText = false; 662 | return returnType; 663 | } 664 | 665 | stream.match(/^([^\]\\]|\\.)+/, true); 666 | 667 | return tokenTypes.linkText; 668 | } 669 | 670 | function footnoteUrl(stream, state) { 671 | // Check if space, and return NULL if so (to avoid marking the space) 672 | if(stream.eatSpace()){ 673 | return null; 674 | } 675 | // Match URL 676 | stream.match(/^[^\s]+/, true); 677 | // Check for link title 678 | if (stream.peek() === undefined) { // End of line, set flag to check next line 679 | state.linkTitle = true; 680 | } else { // More content on line, check if link title 681 | stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true); 682 | } 683 | state.f = state.inline = inlineNormal; 684 | return tokenTypes.linkHref + " url"; 685 | } 686 | 687 | var mode = { 688 | startState: function() { 689 | return { 690 | f: blockNormal, 691 | 692 | prevLine: null, 693 | thisLine: null, 694 | 695 | block: blockNormal, 696 | htmlState: null, 697 | indentation: 0, 698 | 699 | inline: inlineNormal, 700 | text: handleText, 701 | 702 | formatting: false, 703 | linkText: false, 704 | linkHref: false, 705 | linkTitle: false, 706 | code: 0, 707 | em: false, 708 | strong: false, 709 | header: 0, 710 | hr: false, 711 | taskList: false, 712 | list: false, 713 | listStack: [], 714 | quote: 0, 715 | trailingSpace: 0, 716 | trailingSpaceNewLine: false, 717 | strikethrough: false, 718 | fencedChars: null 719 | }; 720 | }, 721 | 722 | copyState: function(s) { 723 | return { 724 | f: s.f, 725 | 726 | prevLine: s.prevLine, 727 | thisLine: s.thisLine, 728 | 729 | block: s.block, 730 | htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState), 731 | indentation: s.indentation, 732 | 733 | localMode: s.localMode, 734 | localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null, 735 | 736 | inline: s.inline, 737 | text: s.text, 738 | formatting: false, 739 | linkTitle: s.linkTitle, 740 | code: s.code, 741 | em: s.em, 742 | strong: s.strong, 743 | strikethrough: s.strikethrough, 744 | header: s.header, 745 | hr: s.hr, 746 | taskList: s.taskList, 747 | list: s.list, 748 | listStack: s.listStack.slice(0), 749 | quote: s.quote, 750 | indentedCode: s.indentedCode, 751 | trailingSpace: s.trailingSpace, 752 | trailingSpaceNewLine: s.trailingSpaceNewLine, 753 | md_inside: s.md_inside, 754 | fencedChars: s.fencedChars 755 | }; 756 | }, 757 | 758 | token: function(stream, state) { 759 | 760 | // Reset state.formatting 761 | state.formatting = false; 762 | 763 | if (stream != state.thisLine) { 764 | var forceBlankLine = state.header || state.hr; 765 | 766 | // Reset state.header and state.hr 767 | state.header = 0; 768 | state.hr = false; 769 | 770 | if (stream.match(/^\s*$/, true) || forceBlankLine) { 771 | blankLine(state); 772 | if (!forceBlankLine) return null 773 | state.prevLine = null 774 | } 775 | 776 | state.prevLine = state.thisLine 777 | state.thisLine = stream 778 | 779 | // Reset state.taskList 780 | state.taskList = false; 781 | 782 | // Reset state.trailingSpace 783 | state.trailingSpace = 0; 784 | state.trailingSpaceNewLine = false; 785 | 786 | state.f = state.block; 787 | var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length; 788 | state.indentationDiff = Math.min(indentation - state.indentation, 4); 789 | state.indentation = state.indentation + state.indentationDiff; 790 | if (indentation > 0) return null; 791 | } 792 | return state.f(stream, state); 793 | }, 794 | 795 | innerMode: function(state) { 796 | if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode}; 797 | if (state.localState) return {state: state.localState, mode: state.localMode}; 798 | return {state: state, mode: mode}; 799 | }, 800 | 801 | blankLine: blankLine, 802 | 803 | getType: getType, 804 | 805 | closeBrackets: "()[]{}''\"\"``", 806 | fold: "markdown" 807 | }; 808 | return mode; 809 | }, "xml"); 810 | 811 | CodeMirror.defineMIME("text/x-markdown", "markdown"); 812 | 813 | }); 814 | --------------------------------------------------------------------------------