├── .gitattributes ├── .gitignore ├── .nojekyll ├── CNAME ├── LICENSE ├── README.md ├── _coverpage.md ├── assets └── fonts │ ├── labmono-license.txt │ ├── labmono-regular-web.woff │ └── labmono-regular-web.woff2 ├── favicon.ico ├── ignored_characters.txt ├── index.html ├── parser ├── assets │ └── fonts │ │ ├── labmono-license.txt │ │ ├── labmono-regular-web.woff │ │ └── labmono-regular-web.woff2 ├── css │ └── styles.css ├── index.html └── js │ ├── MarginConverter.js │ ├── MarginParser.js │ ├── MarginParserExample.js │ ├── TreeModel.js │ └── jquery-3.4.1.min.js └── styles.css /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | assets/img/noun_Margin right_548853.png 4 | assets/img/noun_Margin right_548853.psd 5 | assets/img/logo.png 6 | README.margin 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gamburg/margin/baf615767bd73d86a206d8fd94e057881818fbfa/.nojekyll -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | margin.love -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alex Gamburg 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Philosophy 2 | 3 | Margin is a lightweight markup language for hierarchically structured thought, like notes and to-do lists. 4 | 5 | Its platform-independent structure is both human- and machine-readable. 6 | 7 | This means that Margin can thrive within any plain text editor, and on any hardware -- even paper. 8 | 9 | However unpredictably a thinker prefers to indent, ornament, number, or label their text, Margin will interpret their [**items**](#items) predictably: 10 | 11 | ```margin 12 | Favorite Movies 13 | Eyes Wide Shut 14 | Black Narcissus 15 | Adaptation 16 | 17 | [Is equivalent to...] 18 | 19 | Favorite Movies: 20 | - Eyes Wide Shut 21 | - Black Narcissus 22 | - Adaptation 23 | 24 | [Is equivalent to...] 25 | 26 | ** Favorite Movies ** 27 | > Eyes Wide Shut 28 | > Black Narcissus 29 | > Adaptation 30 | ``` 31 | 32 | This allows the thinker to adopt whatever visual grammar they prefer. 33 | 34 | Items can also be assigned arbitrary [**annotations**](#annotations), which can store meta data: 35 | 36 | ```margin 37 | Favorite Movies 38 | Eyes Wide Shut [year: 1999] 39 | Black Narcissus [year: 1947] 40 | Adaptation [year: 2002] 41 | ``` 42 | 43 | Annotations can also signal how items should be interpreted, e.g. as tasks: 44 | 45 | ```margin 46 | Movies to watch: 47 | [x] Shoplifters 48 | [ ] Lawrence of Arabia 49 | [ ] Inland Empire 50 | ``` 51 | 52 | Margin is especially useful for applications that wish to be less prescriptive in their mental models, leaving it to the user to determine how they'd like to interpret the hierarchical structure. 53 | 54 | Margin aims to shepherd apps away from the tendency to overcomplicate and over-define. 55 | 56 | ### Points of frustration that led to Margin {docsify-ignore} 57 | 58 | There are plenty of well-known, powerful applications that force their own organizational philosophy on the user. And there's nothing inherently wrong with that. 59 | 60 | Nevertheless, when an application's user-facing models of thought... 61 | 1. cannot be easily mapped to the user's own mental models, or 62 | 2. are not justified for the user, 63 | 64 | it can lead to frustration. For example: 65 | - A mobile to-do list app employs a `Flagged` button that takes up valuable home screen space before any tasks have been flagged -- and without knowing whether the user intends to use the flag feature at all. (iOS 13 Reminders) 66 | 67 | - A task management app employs a model of Board -> List -> Card. Lists cannot contain other lists, cards cannot contain other cards, cards cannot contain lists, and so on. (Trello) 68 | 69 | - A to-do list app dictates a set of reserved attributes, like `Labels` and `Filters`, which cannot be removed from the interface. (Todoist) 70 | 71 | I use and love all of the above applications. Their specialization is their strength. Margin's philosophy simply asserts that there is space for a more adaptable standard for stuctured thought. 72 | 73 | In this respect, Margin promotes a common sense approach to modeling thought: simply place the thinker's preferences first. 74 | 75 | This approach begins with a flexible plain text standard. After that, it is the application's job to improve the thinker's experience through specialized tools and prescriptive user-facing models -- as long as the underlying source material remains portable and human-readable. 76 | 77 | Margin is free and open-source. 78 | 79 | ------------------------------- 80 | 81 | # Syntax 82 | 83 | Margin employs an ordered tree data structure whose nodes are called items. Indentation forms the basis of the syntax. 84 | 85 | ## Items 86 | 87 | Each line represents an item: 88 | 89 | ```margin 90 | Shirt 91 | Pants 92 | Shoes 93 | ``` 94 | Each item can have a single parent and multiple children. Indentation alone determines this hierarchy: 95 | ```margin 96 | Shirt 97 | Collar 98 | Sleeves 99 | Buttons 100 | Pants 101 | Belt loop 102 | Pockets 103 | Shoes 104 | Tongue 105 | Laces 106 | ``` 107 | Leading & trailing dashes, colons, asterisks, chevrons, underscores and whitespaces, as well as blank lines, are ignored: 108 | ```margin 109 | ** Key Takeaways ** 110 | ------------------- 111 | Feel free to use plain text decorations freely in order to: 112 | - Help structure your thinking 113 | - Make your plain text documents more easily scannable 114 | ``` 115 | [See the list of all ignored characters.](https://margin.love/ignored_characters.txt) 116 | 117 | ## Annotations 118 | 119 | An annotation is any childless item wrapped in square brackets: 120 | ```margin 121 | I'm a plain old item 122 | [and I'm an annotation] 123 | ``` 124 | Annotations can be used to store meta data: 125 | ```margin 126 | The Crying of Lot 49 127 | [author: Thomas Pynchon] 128 | [publication year: 1966] 129 | [publisher: J. B. Lippincott & Co.] 130 | ``` 131 | An annotation is the child of any inline, non-annotation item: 132 | ```margin 133 | Items: 134 | - Item A 135 | - [I belong to Item B] Item B [I also belong to Item B] 136 | - Item C 137 | [I belong to Item C] 138 | ``` 139 | Because annotations cannot have children, an indented item following an annotation is considered that annotation's parent: 140 | ```margin 141 | Items: 142 | - Item Y 143 | [I belong to Item Y] 144 | - [I belong to Item Z] 145 | Item Z 146 | ``` 147 | Escape an annotation with a backslash: 148 | ```margin 149 | This is an item \[but this is not an annotation] 150 | ``` 151 | Any text up until the (optional) first colon in an annotation may safely be interpreted as the annotation type. 152 | 153 | Annotations with type `population`: 154 | ```margin 155 | Continents 156 | Asia [population: 4,601,371,198] 157 | Africa [population: 1,308,064,195] 158 | Europe [population: 747,182,751] 159 | South America [population: 427,199,446] 160 | North America [population: 366,600,964] 161 | Oceania [population: 42,128,035] 162 | ``` 163 | Annotations with types `waiter` and `host`: 164 | ```margin 165 | Restaurant Staff 166 | Christine [waiter] 167 | Steven [waiter] 168 | Jessica [host] 169 | ``` 170 | An annotation whose type is not understood by the interpreting application may safely be ignored (but should not be discarded): 171 | ```margin 172 | [For example: this annotation won't be utilized unless the app has an interpreter for type "For example".] 173 | ``` 174 | An annotation cannot be nested: 175 | ```margin 176 | [This entire sentence [including this text] represents a single annotation] 177 | ``` 178 | 179 | ## Interpreting Items 180 | 181 | While there are no hard-and-fast rules about how items should be interpreted, the following are good guidelines for most applications. 182 | 183 | ### Tasks 184 | A task is any item that parents an annotation of type `x` or `empty string`: 185 | ```margin 186 | Daily Rituals 187 | [x] Meditate 188 | [ ] Work Out 189 | [ ] Read for 10 minutes 190 | ``` 191 | 192 | ### Links 193 | An annotation of type `http` or `https` represents a link: 194 | ```margin 195 | Some people choose to set their homepage to [http://www.google.com]. 196 | ``` 197 | Text to the left of the annotation not separated by an `empty string` is the link's label: 198 | ```margin 199 | I rarely use Yahoo[http://www.yahoo.com] for search anymore. 200 | ``` 201 | For multi-word labels, wrap the entire label in parentheses: 202 | ```margin 203 | Sometimes I do read (Yahoo News)[https://news.yahoo.com], though. 204 | ``` 205 | 206 | ### Indexes 207 | An index is any item that parents an annotation of type `filter`: 208 | ```margin 209 | Now Playing [filter: release date is before tomorrow] 210 | Coming Soon [filter: release date is after today] 211 | ``` 212 | An application may use the specified query to filter for certain nodes under certain conditions of interaction. For most applications, the default filter for a given task (when no filter is specified) would be that task's children. But this is outside the scope of the markup language itself. 213 | 214 | ### Document Parent 215 | Every Margin document has an implied document parent, an item that parents every top-level item in the document. This item can also have annotations, which can be useful as document-level meta data. These annotations are defined as the first apparently parentless annotation in the document: 216 | ```margin 217 | [Kid Reader Pro] 218 | [Reader Name: Kit Mapache] 219 | 220 | Read: 221 | - The Phantom Tollbooth 222 | - A Wrinkle in Time 223 | - Charlotte's Web 224 | 225 | Unread: 226 | - Where the Wild Things Are 227 | ``` 228 | 229 | # Try it out 230 | 231 | The Margin JavaScript parser is currently in alpha. [You can try it out for yourself here](https://margin.love/parser), but note that some functionality defined in this spec will not yet function properly. 232 | 233 | # Implementations 234 | 235 | - This repo contains the original Javascript implementation. 236 | - [MarginRB](https://github.com/burlesona/margin-rb) - Ruby implementation by @burlesona 237 | 238 | # Questions 239 | 240 | **Why not TaskPaper?** 241 | 242 | [TaskPaper](https://www.taskpaper.com) is a great, minimal app for creating to-do lists. Some readers might feel that Margin's capabilities are redundant, but I believe Margin stands apart in several key ways: 243 | 244 | - Margin is not an app, but a markup language. 245 | - Margin is hierarchically less prescriptive than TaskPaper. Where TaskPaper splits items into `projects`, `tasks`, and `notes`, Margin sees only items. A top-level item in Margin *could* be considered a project, but it could also just as easily be considered a list, a note, a task, a chapter, an employee, an index, etc. 246 | - Margin is syntactically less prescriptive than [TaskPaper's formatting](https://guide.taskpaper.com/getting-started/). TaskPaper categorizes items by their ornamentation (`projects` end with a colon, `tasks` begin with a dash, and `notes` must not fall into either of those two categories). Margin intentionally avoids such definitions, allowing the user to ornament (or not) plain text in nearly any format they prefer. 247 | 248 | **Indentation? Human-readable? Won't a complicated Margin document just end up as a jumbled mess of deeply indented text blocks and annotations?** 249 | 250 | Margin isn't meant for storing complex databases. It's meant to make text-based structured thought portable and platform-independent. In the same way that Markdown is built to translate into HTML, but you wouldn't build a web app in Markdown, so Margin too has its limitations. The idea is to de-formalize any unnecessary syntactic requirements, leaving only indentations and a select number of special operators to dictate the parsing of the language. Keeping it simple has its benefits, but it also has its costs. 251 | 252 | **What is the preferred extension for Margin files?** 253 | 254 | Margin files use the extension `.margin`. 255 | 256 | **Does Margin support multi-line items?** 257 | 258 | No. But if you're writing in Margin and you really want items to span multiple lines, feel free to use whatever syntax appeals to you to acheive that. Margin certainly doesn't care what you do in the privacy of your own plain text editor. Just don't expect those multi-line items to be interpreted properly by a given application. 259 | 260 | **Where can I send feedback?** 261 | 262 | Please submit any feedback as an issue on [Margin's public GitHub repository](https://github.com/gamburg/margin/issues). 263 | -------------------------------------------------------------------------------- /_coverpage.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | > ⊙ 4 | # Margin 5 | 6 | > Lightweight markup designed for an open mind 7 | 8 | - The plain text language for list-making, note-taking, and to-dos. 9 | - Thinkers determine their own organizational models. 10 | - Infinitely extensible, inherently readable. 11 | 12 | 13 | [Learn Margin →](#philosophy) 14 | [Try it out ✎](https://margin.love/parser) 15 | [GitHub ♡](https://github.com/gamburg/margin) 16 | 17 | 18 | 19 | ![color](#f0f0f0) 20 | -------------------------------------------------------------------------------- /assets/fonts/labmono-license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Martin Wecke (http://martinwecke.de), 2 | with Reserved Font Name Lab Mono. 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /assets/fonts/labmono-regular-web.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gamburg/margin/baf615767bd73d86a206d8fd94e057881818fbfa/assets/fonts/labmono-regular-web.woff -------------------------------------------------------------------------------- /assets/fonts/labmono-regular-web.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gamburg/margin/baf615767bd73d86a206d8fd94e057881818fbfa/assets/fonts/labmono-regular-web.woff2 -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gamburg/margin/baf615767bd73d86a206d8fd94e057881818fbfa/favicon.ico -------------------------------------------------------------------------------- /ignored_characters.txt: -------------------------------------------------------------------------------- 1 | U+0020 (whitespace) 2 | U+0009 (tab) 3 | U+002A (*) 4 | U+FE61 (﹡) 5 | U+FF0A (*) 6 | U+002D (-) 7 | U+2013 (–) 8 | U+2014 (—) 9 | U+005F (_) 10 | U+003A (:) 11 | U+003E (>) 12 | U+002B (+) 13 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 |
20 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /parser/assets/fonts/labmono-license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Martin Wecke (http://martinwecke.de), 2 | with Reserved Font Name Lab Mono. 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /parser/assets/fonts/labmono-regular-web.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gamburg/margin/baf615767bd73d86a206d8fd94e057881818fbfa/parser/assets/fonts/labmono-regular-web.woff -------------------------------------------------------------------------------- /parser/assets/fonts/labmono-regular-web.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gamburg/margin/baf615767bd73d86a206d8fd94e057881818fbfa/parser/assets/fonts/labmono-regular-web.woff2 -------------------------------------------------------------------------------- /parser/css/styles.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Lab Mono'; 3 | src: url('../assets/fonts/labmono-regular-web.woff2') format('woff2'), 4 | url('../assets/fonts/labmono-regular-web.woff') format('woff'); 5 | } 6 | 7 | html, body { 8 | height: 100%; 9 | font-family: 'Lab Mono', 'Courier', monospace; 10 | margin: 0; 11 | } 12 | 13 | .input, .output { 14 | font-family: inherit; 15 | font-size: .8em; 16 | height: 100%; 17 | width: 100%; 18 | 19 | padding: 2em; 20 | -moz-box-sizing: border-box; 21 | -webkit-box-sizing: border-box; 22 | box-sizing: border-box; 23 | 24 | border: none; 25 | outline: none; 26 | 27 | -moz-tab-size : 4; 28 | -o-tab-size : 4; 29 | tab-size : 4; 30 | } 31 | 32 | .input { 33 | float: left; 34 | cursor:text; 35 | } 36 | 37 | .output { 38 | float: right; 39 | white-space: pre; 40 | overflow: scroll; 41 | } 42 | 43 | header { 44 | -moz-box-sizing: border-box; 45 | -webkit-box-sizing: border-box; 46 | box-sizing: border-box; 47 | padding: 1em 2em; 48 | } 49 | 50 | input[type="radio"]:checked+label { 51 | text-decoration: underline; 52 | } 53 | 54 | input[type="radio"]+label { 55 | font-size: .9em; 56 | padding: 0 .5em 0 .2em; 57 | vertical-align: middle; 58 | white-space: nowrap; 59 | } 60 | 61 | input[type="radio"] { 62 | display: none; 63 | } 64 | 65 | input[type="radio"]+label { 66 | cursor: pointer; 67 | } 68 | 69 | h2 { 70 | font-size:2em; 71 | font-weight: bold; 72 | margin-top: .4em; 73 | margin-bottom: .5em; 74 | } 75 | 76 | .light { 77 | background: #f6f5f5; 78 | color: #33313b; 79 | } 80 | 81 | .dark { 82 | background: #33313b; 83 | color: #f6f5f5; 84 | } 85 | 86 | div { 87 | display: inline-block; 88 | height: 100%; 89 | width: 50%; 90 | } 91 | -------------------------------------------------------------------------------- /parser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Try Margin 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

Input

15 | 16 | 17 | 18 |
19 | 24 |
25 |
26 |

Output

27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /parser/js/MarginConverter.js: -------------------------------------------------------------------------------- 1 | function convert_margin( root, output_format ) { 2 | switch(output_format) { 3 | case 'json': 4 | return JSON.stringify(root.model, null, 5); 5 | break; 6 | 7 | case 'markdown': 8 | return 'markdown output here'; 9 | break; 10 | 11 | case 'pretty': 12 | return ' I have a bike
'; 13 | break; 14 | } 15 | return null; 16 | } 17 | -------------------------------------------------------------------------------- /parser/js/MarginParser.js: -------------------------------------------------------------------------------- 1 | class MarginTree extends TreeModel { 2 | } 3 | 4 | class MarginItem { 5 | 6 | constructor( parseable_text ) { 7 | this.raw_data = get_top_level_text( parseable_text ); 8 | this.value = this.get_value(); 9 | this.annotations = this.set_annotations(); 10 | this.children = []; 11 | var _this = this; // allows this instance to be visible inside forEach loop 12 | 13 | var child_parseable_text = get_child_text_trees( parseable_text ); 14 | console.log(child_parseable_text); 15 | 16 | child_parseable_text.forEach(function(child_text) { 17 | var child_item = new MarginItem( child_text ); 18 | _this.children.push( child_item ); 19 | }); 20 | } 21 | 22 | get_value() { 23 | // leading characters regex: /^([-_> ])*/g; 24 | // trailing characters regex: /(([-_>* ])+$)/g; 25 | // annotations regex = ??????? // <-----TODO 26 | var regex_trim_these = /(^([-_>* \t])*)|(([-_>* \t])+$)/g; 27 | return this.raw_data.replace( regex_trim_these, ''); 28 | } 29 | 30 | trim_characters( str, characters_to_remove, leading = true ) { 31 | 32 | } 33 | 34 | get_annotations( key = false ) { 35 | if( !key ) { 36 | return this.annotations; 37 | } 38 | return this.annotations[key]; 39 | } 40 | 41 | set_annotations() { 42 | // bracketed segments regex: /\[(?:[^\]\[]+|\[(?:[^\]\[]+|\[[^\]\[]*\])*\])*\]/g 43 | var annotations = {}; 44 | var key_value_separator = ':'; 45 | var regex_annotations = /\[(?:[^\]\[]+|\[(?:[^\]\[]+|\[[^\]\[]*\])*\])*\]/g; 46 | var raw_annotations = this.raw_data.match( regex_annotations ); 47 | 48 | if( raw_annotations ) { 49 | raw_annotations.forEach(function( raw_annotation ) { 50 | var key; 51 | var value = null; 52 | var raw_annotation_unwrapped = raw_annotation.slice(1,-1); // remove ] & [ 53 | var key_value_separator_index = raw_annotation_unwrapped.indexOf( key_value_separator ); 54 | if( key_value_separator_index < 0 ) { // no annotation separator found 55 | key = raw_annotation_unwrapped; 56 | } else { 57 | key = raw_annotation_unwrapped.substring(0, key_value_separator_index); 58 | value = raw_annotation_unwrapped.substring(key_value_separator_index + 1, raw_annotation_unwrapped.length); 59 | } 60 | annotations[key] = value;// <-------- TODO: assign annotation's value to annotation's key(not currently functioning) 61 | }); 62 | } 63 | return annotations; 64 | } 65 | } 66 | 67 | function get_margin_item( text ) { 68 | var root_text = "root\n"; 69 | var shifted_text = root_text.concat( shift_right( text ) ); 70 | var parseable_text = conform_text_for_parsing( shifted_text ); 71 | return new MarginItem( parseable_text ); 72 | } 73 | 74 | function conform_text_for_parsing( text ) { 75 | return remove_blank_lines( text ); 76 | } 77 | 78 | function remove_blank_lines( text ) { 79 | return text.replace(/^\s*[\r\n]/gm, ''); 80 | } 81 | 82 | function get_child_text_trees( text_tree ) { 83 | var child_texts = []; 84 | 85 | var lines = text_tree.split('\n'); 86 | var top_level = get_line_indentation_number( lines[0] ); 87 | 88 | // Strip off parent text: 89 | for(var i = 0; i < lines.length; i++) { 90 | if( get_line_indentation_number( lines[i] ) === top_level ) { 91 | lines.splice(i, 1); 92 | } 93 | } 94 | 95 | return get_margin_text_from_line_array( lines ); 96 | 97 | } 98 | 99 | function get_top_level_text( text_tree ) { 100 | var lines = text_tree.split('\n'); 101 | return lines[0]; 102 | } 103 | 104 | function get_margin_text_from_line_array( lines ) { 105 | 106 | var child_texts = []; 107 | var current_indentation = null; 108 | var current_child_text = ""; 109 | 110 | for(var i = 0; i < lines.length; i++) { 111 | if( !current_indentation ) { 112 | current_indentation = get_line_indentation_number( lines[i] ); 113 | current_child_text += lines[i]; 114 | } else { 115 | if( get_line_indentation_number( lines[i] ) === current_indentation ) { 116 | child_texts.push( current_child_text ); 117 | current_indentation = get_line_indentation_number( lines[i] ); 118 | current_child_text = lines[i]; 119 | } else { 120 | current_child_text += '\n' + lines[i]; 121 | } 122 | } 123 | } 124 | 125 | if(current_child_text) { 126 | child_texts.push( current_child_text ); 127 | } 128 | 129 | return child_texts; 130 | } 131 | 132 | function get_line_indentation_number(text) { 133 | return text.search(/\S|$/); 134 | } 135 | 136 | function shift_right( text, indenter = " " ) { 137 | var lines = text.split('\n'); 138 | var shifted_lines = []; 139 | 140 | for(var i = 0; i < lines.length; i++) { 141 | shifted_lines.push( indenter.concat(lines[i]) ); 142 | } 143 | 144 | return shifted_lines.join("\n"); 145 | } 146 | -------------------------------------------------------------------------------- /parser/js/MarginParserExample.js: -------------------------------------------------------------------------------- 1 | jQuery( document ).ready(function() { 2 | var input_area = jQuery('.input'); 3 | var output_area = jQuery('.output'); 4 | var ouput_select = jQuery('.output_wrapper input[type=radio]'); 5 | var input_radios = jQuery('.input_wrapper input[type=radio]'); 6 | var update_triggers = jQuery('.input, .output, input[type=radio]'); 7 | var output_radio_selector = 'input[name="output"]:checked'; 8 | 9 | make_textarea_margin_friendly( input_area ); 10 | update_input_area_on_select( input_area, input_radios ); 11 | update_output_area_on_change( update_triggers, input_area, output_area, output_radio_selector ); 12 | }); 13 | 14 | function update_input_area_on_select( input_area, trigger_elements ) { 15 | trigger_elements.on('change', function() { 16 | var sample_name_to_find = get_radio_input_selected( trigger_elements ).val(); 17 | input_samples.forEach(function( sample ) { 18 | if( sample.name === sample_name_to_find ) { 19 | input_area.text( sample.data ); 20 | } 21 | }); 22 | }).triggerHandler('change'); 23 | } 24 | 25 | function move_focus_to_end_of_input( e ) { 26 | val = e.val(); 27 | e.focus().val("").val(val); 28 | } 29 | 30 | function update_output_area_on_change( update_triggers, input_area, output_area, output_radio_selector ) { 31 | update_triggers.on('change keyup paste', function() { 32 | var converted_text = get_converted_text( input_area.val(), get_output_format( output_radio_selector ) ); 33 | switch( get_display_format(output_radio_selector) ) { 34 | case 'html': 35 | output_area.html( converted_text ); 36 | break; 37 | case 'text': 38 | output_area.text( converted_text ); 39 | break; 40 | } 41 | }).triggerHandler('change'); 42 | } 43 | 44 | function get_output_format( selector ) { 45 | return document.querySelector(selector).value; 46 | } 47 | 48 | function get_display_format( selector ) { 49 | return document.querySelector(selector).dataset.display; 50 | } 51 | 52 | function get_radio_input_selected( input_elements ) { 53 | return input_elements.parent().find( 'input[type=radio]:checked' ); 54 | } 55 | 56 | function get_converted_text( input_text, output_format ) { 57 | var sampleTree = new MarginTree(); 58 | var root = sampleTree.parse( get_margin_item(input_text) ); 59 | return convert_margin( root, output_format ); 60 | } 61 | 62 | /********************* 63 | 64 | Global Variables 65 | 66 | **********************/ 67 | 68 | var input_samples = [ 69 | { 70 | name: 'shopping', 71 | data: ' ** Shopping **\n [x] Groceries\n [x] Milk\n [x] Kale\n [ ] Frozen Fish [Note: Any sort of white fish, not cod]\n\n ** Projects **\n Portfolio Website\n Front-end\n [ ] Disallow zoom on mobile\n [ ] Fix homepage grid on mobile\n Back-end\n Wordpress\n [ ] Update plugins [date: 2019/07/07]\n Server\n [ ] Renew hosting [date: 2020/01/07]\n [ ] Upgrade to PHP 7 [date: 2020/02/14]' 72 | }, 73 | { 74 | name: 'notes', 75 | data: '\'Typograpy That Works\'\n\n\tCourse Notes\n\t\tGraphic design is all about lining things up (often in a grid)\n\t\tStandard Alignments\n\t\t\t> Centered: Formal, symmetrical\n\t\t\t> Justified: Economical, saves space\n\t\t\t> Flush Left: Organic\n\t\t\t> Flush Right: Unusual, lends a dynamism\n\t\tThere should be a self-contained logic to the chosen grid\n\t\tMultiple layout ideas should be tested rapidly\n\n\tClass Assignments\n\t\t- Project 1 [due: 2019/01/12]\n\t\t- Midterm [due: 2019/02/18]\n\t\t- Final Project [due: 2019/03/14]' 76 | }, 77 | { 78 | name: 'reading', 79 | data: 'The Crying of Lot 49\n\t[author: Thomas Pynchon]\n\t[publication year: 1966]\n\t[publisher: J. B. Lippincott & Co.]\n\t[status: read]\n\nMy Struggle: Book 1\n\t[author: Karl Ove Knausgaard]\n\t[publication year: 2013]\n\t[publisher: Farrar, Straus and Giroux]\n\t[status: unread]\n\nTrick Mirror: Reflections on Self-Delusion\n\t[author: Jia Tolentino]\n\t[publication year: 2019]\n\t[publisher: Random House]\n\t[status: unread]' 80 | } 81 | ] 82 | 83 | 84 | /* ------------------------------------------------------------------------- */ 85 | 86 | function make_textarea_margin_friendly( textarea ) { 87 | enable_tab_in_textarea( textarea ); 88 | preserve_newline_indentation_in_textarea( textarea ); 89 | } 90 | 91 | function enable_tab_in_textarea( textarea ) { 92 | textarea.keydown(function(e) { 93 | if(e.keyCode === 9) { // tab was pressed 94 | // get caret position/selection 95 | var start = this.selectionStart; 96 | end = this.selectionEnd; 97 | 98 | var $this = $(this); 99 | 100 | // set textarea value to: text before caret + tab + text after caret 101 | $this.val($this.val().substring(0, start) 102 | + "\t" 103 | + $this.val().substring(end)); 104 | 105 | // put caret at right position again 106 | this.selectionStart = this.selectionEnd = start + 1; 107 | 108 | // prevent the focus lose 109 | return false; 110 | } 111 | }); 112 | } 113 | 114 | function preserve_newline_indentation_in_textarea( textarea ) { 115 | textarea.keydown(function(e){ 116 | if(e.keyCode == 13){ 117 | var cursorPos = this.selectionStart; 118 | var curentLine = this.value.substr(0, this.selectionStart).split("\n").pop(); 119 | var indent = curentLine.match(/^\s*/)[0]; 120 | var value = this.value; 121 | var textBefore = value.substring(0, cursorPos ); 122 | var textAfter = value.substring( cursorPos, value.length ); 123 | 124 | e.preventDefault(); // avoid creating a new line since we do it ourself 125 | this.value = textBefore + "\n" + indent + textAfter; 126 | setCaretPosition(this, cursorPos + indent.length + 1); // +1 is for the \n 127 | } 128 | }); 129 | } 130 | 131 | function setCaretPosition(ctrl, pos) { 132 | if(ctrl.setSelectionRange) { 133 | ctrl.focus(); 134 | ctrl.setSelectionRange(pos,pos); 135 | } 136 | else if (ctrl.createTextRange) { 137 | var range = ctrl.createTextRange(); 138 | range.collapse(true); 139 | range.moveEnd('character', pos); 140 | range.moveStart('character', pos); 141 | range.select(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /parser/js/TreeModel.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2013 João Nuno Silva 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | */ 26 | 27 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.TreeModel = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0; 95 | }; 96 | 97 | function addChild(self, child, insertIndex) { 98 | var index; 99 | 100 | if (!(child instanceof Node)) { 101 | throw new TypeError('Child must be of type Node.'); 102 | } 103 | 104 | child.parent = self; 105 | if (!(self.model[self.config.childrenPropertyName] instanceof Array)) { 106 | self.model[self.config.childrenPropertyName] = []; 107 | } 108 | 109 | if (hasComparatorFunction(self)) { 110 | // Find the index to insert the child 111 | index = findInsertIndex( 112 | self.config.modelComparatorFn, 113 | self.model[self.config.childrenPropertyName], 114 | child.model); 115 | 116 | // Add to the model children 117 | self.model[self.config.childrenPropertyName].splice(index, 0, child.model); 118 | 119 | // Add to the node children 120 | self.children.splice(index, 0, child); 121 | } else { 122 | if (insertIndex === undefined) { 123 | self.model[self.config.childrenPropertyName].push(child.model); 124 | self.children.push(child); 125 | } else { 126 | if (insertIndex < 0 || insertIndex > self.children.length) { 127 | throw new Error('Invalid index.'); 128 | } 129 | self.model[self.config.childrenPropertyName].splice(insertIndex, 0, child.model); 130 | self.children.splice(insertIndex, 0, child); 131 | } 132 | } 133 | return child; 134 | } 135 | 136 | Node.prototype.addChild = function (child) { 137 | return addChild(this, child); 138 | }; 139 | 140 | Node.prototype.addChildAtIndex = function (child, index) { 141 | if (hasComparatorFunction(this)) { 142 | throw new Error('Cannot add child at index when using a comparator function.'); 143 | } 144 | 145 | return addChild(this, child, index); 146 | }; 147 | 148 | Node.prototype.setIndex = function (index) { 149 | if (hasComparatorFunction(this)) { 150 | throw new Error('Cannot set node index when using a comparator function.'); 151 | } 152 | 153 | if (this.isRoot()) { 154 | if (index === 0) { 155 | return this; 156 | } 157 | throw new Error('Invalid index.'); 158 | } 159 | 160 | if (index < 0 || index >= this.parent.children.length) { 161 | throw new Error('Invalid index.'); 162 | } 163 | 164 | var oldIndex = this.parent.children.indexOf(this); 165 | 166 | this.parent.children.splice(index, 0, this.parent.children.splice(oldIndex, 1)[0]); 167 | 168 | this.parent.model[this.parent.config.childrenPropertyName] 169 | .splice(index, 0, this.parent.model[this.parent.config.childrenPropertyName].splice(oldIndex, 1)[0]); 170 | 171 | return this; 172 | }; 173 | 174 | Node.prototype.getPath = function () { 175 | var path = []; 176 | (function addToPath(node) { 177 | path.unshift(node); 178 | if (!node.isRoot()) { 179 | addToPath(node.parent); 180 | } 181 | })(this); 182 | return path; 183 | }; 184 | 185 | Node.prototype.getIndex = function () { 186 | if (this.isRoot()) { 187 | return 0; 188 | } 189 | return this.parent.children.indexOf(this); 190 | }; 191 | 192 | /** 193 | * Parse the arguments of traversal functions. These functions can take one optional 194 | * first argument which is an options object. If present, this object will be stored 195 | * in args.options. The only mandatory argument is the callback function which can 196 | * appear in the first or second position (if an options object is given). This 197 | * function will be saved to args.fn. The last optional argument is the context on 198 | * which the callback function will be called. It will be available in args.ctx. 199 | * 200 | * @returns Parsed arguments. 201 | */ 202 | function parseArgs() { 203 | var args = {}; 204 | if (arguments.length === 1) { 205 | if (typeof arguments[0] === 'function') { 206 | args.fn = arguments[0]; 207 | } else { 208 | args.options = arguments[0]; 209 | } 210 | } else if (arguments.length === 2) { 211 | if (typeof arguments[0] === 'function') { 212 | args.fn = arguments[0]; 213 | args.ctx = arguments[1]; 214 | } else { 215 | args.options = arguments[0]; 216 | args.fn = arguments[1]; 217 | } 218 | } else { 219 | args.options = arguments[0]; 220 | args.fn = arguments[1]; 221 | args.ctx = arguments[2]; 222 | } 223 | args.options = args.options || {}; 224 | if (!args.options.strategy) { 225 | args.options.strategy = 'pre'; 226 | } 227 | if (!walkStrategies[args.options.strategy]) { 228 | throw new Error('Unknown tree walk strategy. Valid strategies are \'pre\' [default], \'post\' and \'breadth\'.'); 229 | } 230 | return args; 231 | } 232 | 233 | Node.prototype.walk = function () { 234 | var args; 235 | args = parseArgs.apply(this, arguments); 236 | walkStrategies[args.options.strategy].call(this, args.fn, args.ctx); 237 | }; 238 | 239 | walkStrategies.pre = function depthFirstPreOrder(callback, context) { 240 | var i, childCount, keepGoing; 241 | keepGoing = callback.call(context, this); 242 | for (i = 0, childCount = this.children.length; i < childCount; i++) { 243 | if (keepGoing === false) { 244 | return false; 245 | } 246 | keepGoing = depthFirstPreOrder.call(this.children[i], callback, context); 247 | } 248 | return keepGoing; 249 | }; 250 | 251 | walkStrategies.post = function depthFirstPostOrder(callback, context) { 252 | var i, childCount, keepGoing; 253 | for (i = 0, childCount = this.children.length; i < childCount; i++) { 254 | keepGoing = depthFirstPostOrder.call(this.children[i], callback, context); 255 | if (keepGoing === false) { 256 | return false; 257 | } 258 | } 259 | keepGoing = callback.call(context, this); 260 | return keepGoing; 261 | }; 262 | 263 | walkStrategies.breadth = function breadthFirst(callback, context) { 264 | var queue = [this]; 265 | (function processQueue() { 266 | var i, childCount, node; 267 | if (queue.length === 0) { 268 | return; 269 | } 270 | node = queue.shift(); 271 | for (i = 0, childCount = node.children.length; i < childCount; i++) { 272 | queue.push(node.children[i]); 273 | } 274 | if (callback.call(context, node) !== false) { 275 | processQueue(); 276 | } 277 | })(); 278 | }; 279 | 280 | Node.prototype.all = function () { 281 | var args, all = []; 282 | args = parseArgs.apply(this, arguments); 283 | args.fn = args.fn || k(true); 284 | walkStrategies[args.options.strategy].call(this, function (node) { 285 | if (args.fn.call(args.ctx, node)) { 286 | all.push(node); 287 | } 288 | }, args.ctx); 289 | return all; 290 | }; 291 | 292 | Node.prototype.first = function () { 293 | var args, first; 294 | args = parseArgs.apply(this, arguments); 295 | args.fn = args.fn || k(true); 296 | walkStrategies[args.options.strategy].call(this, function (node) { 297 | if (args.fn.call(args.ctx, node)) { 298 | first = node; 299 | return false; 300 | } 301 | }, args.ctx); 302 | return first; 303 | }; 304 | 305 | Node.prototype.drop = function () { 306 | var indexOfChild; 307 | if (!this.isRoot()) { 308 | indexOfChild = this.parent.children.indexOf(this); 309 | this.parent.children.splice(indexOfChild, 1); 310 | this.parent.model[this.config.childrenPropertyName].splice(indexOfChild, 1); 311 | this.parent = undefined; 312 | delete this.parent; 313 | } 314 | return this; 315 | }; 316 | 317 | return TreeModel; 318 | })(); 319 | 320 | },{"find-insert-index":2,"mergesort":3}],2:[function(require,module,exports){ 321 | module.exports = (function () { 322 | 'use strict'; 323 | 324 | /** 325 | * Find the index to insert an element in array keeping the sort order. 326 | * 327 | * @param {function} comparatorFn The comparator function which sorted the array. 328 | * @param {array} arr The sorted array. 329 | * @param {object} el The element to insert. 330 | */ 331 | function findInsertIndex(comparatorFn, arr, el) { 332 | var i, len; 333 | for (i = 0, len = arr.length; i < len; i++) { 334 | if (comparatorFn(arr[i], el) > 0) { 335 | break; 336 | } 337 | } 338 | return i; 339 | } 340 | 341 | return findInsertIndex; 342 | })(); 343 | 344 | },{}],3:[function(require,module,exports){ 345 | module.exports = (function () { 346 | 'use strict'; 347 | 348 | /** 349 | * Sort an array using the merge sort algorithm. 350 | * 351 | * @param {function} comparatorFn The comparator function. 352 | * @param {array} arr The array to sort. 353 | * @returns {array} The sorted array. 354 | */ 355 | function mergeSort(comparatorFn, arr) { 356 | var len = arr.length, firstHalf, secondHalf; 357 | if (len >= 2) { 358 | firstHalf = arr.slice(0, len / 2); 359 | secondHalf = arr.slice(len / 2, len); 360 | return merge(comparatorFn, mergeSort(comparatorFn, firstHalf), mergeSort(comparatorFn, secondHalf)); 361 | } else { 362 | return arr.slice(); 363 | } 364 | } 365 | 366 | /** 367 | * The merge part of the merge sort algorithm. 368 | * 369 | * @param {function} comparatorFn The comparator function. 370 | * @param {array} arr1 The first sorted array. 371 | * @param {array} arr2 The second sorted array. 372 | * @returns {array} The merged and sorted array. 373 | */ 374 | function merge(comparatorFn, arr1, arr2) { 375 | var result = [], left1 = arr1.length, left2 = arr2.length; 376 | while (left1 > 0 && left2 > 0) { 377 | if (comparatorFn(arr1[0], arr2[0]) <= 0) { 378 | result.push(arr1.shift()); 379 | left1--; 380 | } else { 381 | result.push(arr2.shift()); 382 | left2--; 383 | } 384 | } 385 | if (left1 > 0) { 386 | result.push.apply(result, arr1); 387 | } else { 388 | result.push.apply(result, arr2); 389 | } 390 | return result; 391 | } 392 | 393 | return mergeSort; 394 | })(); 395 | 396 | },{}]},{},[1])(1) 397 | }); 398 | -------------------------------------------------------------------------------- /parser/js/jquery-3.4.1.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0 p:last-child a, 20 | section.cover .cover-main > p:last-child a:last-child { 21 | border: none; 22 | background: none; 23 | color: inherit; 24 | text-decoration: underline; 25 | } 26 | 27 | section.cover ul { 28 | max-width: none; 29 | } 30 | 31 | .markdown-section ul, 32 | .markdown-section ol { 33 | padding-left: 0; 34 | } 35 | 36 | .markdown-section ul { 37 | margin-left: -10px; 38 | } 39 | 40 | .markdown-section ul li { 41 | padding-left: 10px; 42 | } 43 | --------------------------------------------------------------------------------