├── .gitattributes ├── .gitignore ├── .travis.yml ├── Default.sublime-commands ├── LICENSE.md ├── Main.sublime-menu ├── Markdown.sublime-build ├── MarkdownPreview.py ├── MarkdownPreview.sublime-settings ├── README.md ├── css ├── github.css ├── markdown.css └── pygments │ ├── github.css │ └── github2014.css ├── dependencies.json ├── desktop ├── .gitignore ├── README.md ├── __init__.py ├── dialog.py └── windows.py ├── docs ├── src │ └── markdown │ │ ├── _snippets │ │ ├── mathjax.md │ │ └── refs.md │ │ ├── changes.md │ │ ├── extras.md │ │ ├── images │ │ └── sublimetext-markdown-preview.gif │ │ ├── index.md │ │ ├── install.md │ │ ├── license.md │ │ └── usage.md └── theme │ ├── extra-d04c85ed4a.css │ └── extra-d8800ea088.js ├── js ├── math_config.js └── uml.js ├── markdown_settings.py ├── markdown_wrapper.py ├── messages.json ├── mkdocs.yml ├── samples ├── customized-template-sample.html └── sample.md ├── setup.cfg └── tests ├── abbreviations.md ├── footnotes.md ├── logo-revolunet-carre.jpg ├── references.md └── test.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | tests/*.html 4 | site/* 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | install: 5 | - pip install flake8 6 | - pip install flake8-docstrings 7 | - pip install pep8-naming 8 | script: 9 | - flake8 . 10 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Markdown Preview: Preview in Browser", 4 | "command": "markdown_preview_select", 5 | "args": { 6 | "target": "browser" 7 | } 8 | }, 9 | { 10 | "caption": "Markdown Preview: Export HTML in Sublime Text", 11 | "command": "markdown_preview_select", 12 | "args": { 13 | "target": "sublime" 14 | } 15 | }, 16 | { 17 | "caption": "Markdown Preview: Save to HTML", 18 | "command": "markdown_preview_select", 19 | "args": { 20 | "target": "save" 21 | } 22 | }, 23 | { 24 | "caption": "Markdown Preview: Copy to Clipboard", 25 | "command": "markdown_preview_select", 26 | "args": { 27 | "target": "clipboard" 28 | } 29 | }, 30 | 31 | { 32 | "caption": "Markdown Preview: Open Markdown Cheat sheet", 33 | "command": "markdown_cheatsheet", 34 | "args": {} 35 | } 36 | ] 37 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2015 Julien Bouquillon, revolunet 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Preferences", 4 | "mnemonic": "n", 5 | "id": "preferences", 6 | "children": 7 | [ 8 | { 9 | "caption": "Package Settings", 10 | "mnemonic": "P", 11 | "id": "package-settings", 12 | "children": 13 | [ 14 | { 15 | "caption": "Markdown Preview", 16 | "children": 17 | [ 18 | { 19 | "command": "open_file", 20 | "args": {"file": "${packages}/Markdown Preview/MarkdownPreview.sublime-settings"}, 21 | "caption": "Settings – Default" 22 | }, 23 | { 24 | "command": "open_file", 25 | "args": {"file": "${packages}/User/MarkdownPreview.sublime-settings"}, 26 | "caption": "Settings – User" 27 | }, 28 | { "caption": "-" } 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | ] 36 | -------------------------------------------------------------------------------- /Markdown.sublime-build: -------------------------------------------------------------------------------- 1 | { 2 | "target": "markdown_build", 3 | "selector": "text.html.markdown" 4 | } 5 | -------------------------------------------------------------------------------- /MarkdownPreview.sublime-settings: -------------------------------------------------------------------------------- 1 | /* 2 | Markdown Preview default settings 3 | */ 4 | { 5 | /* 6 | Sets the default opener for HTML files 7 | 8 | default - Use the system default HTML viewer 9 | other - Set a full path to any executable. ex: /Applications/Google Chrome Canary.app or /Applications/Firefox.app 10 | */ 11 | "browser": "default", 12 | 13 | /* 14 | Sets the parser used for building markdown to HTML. 15 | 16 | NOTE: The parser setting is not for the preview commands. 17 | The previews have separate commands for each parser markdown. 18 | 19 | Warning for github API: if you have a ST2 linux build, Python is not built with SSL so it may not work 20 | 21 | default - The current default parser is python-markdown parser. 22 | markdown - Use the built-in python-markdown parser 23 | github - Use the github API to convert markdown, so you can use GitHub flavored Markdown, see https://help.github.com/articles/github-flavored-markdown/ 24 | */ 25 | "parser": "markdown", 26 | 27 | /* 28 | By default, Markdown Preview builds the HTML in the source directory. 29 | It expects the file to exist on disk. It pops up the build output panel etc. 30 | 31 | If you wish to override this behavior, you can change "build_action" 32 | 33 | build - The default build behavior. 34 | browser - Preview the file in your browser. 35 | clipboard - Copy the HTML output to the clipboard. 36 | sublime - Export the HTML to a Sublime tab. 37 | save - Run the normal save command that outputs to the source directory. 38 | It will also prompt for "save as" if the file does not exit on disk. 39 | 40 | All the build options use the default parser defined above in "parser" 41 | */ 42 | "build_action": "build", 43 | 44 | /* 45 | If Pygments is being used, you may want to inject one of the Pygment styles provided into the HTML. 46 | If so, enable this. 47 | */ 48 | "pygments_inject_css": true, 49 | 50 | /* 51 | Name of the Pygments style to inject. Available styles are the styles provided by pygments 52 | plus "github" and "github2014". 53 | */ 54 | "pygments_style": "github", 55 | 56 | /* 57 | This is the class to prepend to the pygments CSS styles. Make sure it matches whatever class(es) 58 | you've specified in the extension that controls Pygments highlighting. CodeHilite's default is 59 | "codehilite". 60 | */ 61 | "pygments_css_class": "codehilite", 62 | 63 | /* 64 | Markdown extension configuration. 65 | 66 | To specify a function in this JSON configuration, create an object with the key "!!python/name" 67 | and set it to the import path to the function "module.submodule.etc.function". 68 | */ 69 | "markdown_extensions": [ 70 | // Python Markdown Extra with SuperFences. 71 | // You can't include "extra" and "superfences" 72 | // as "fenced_code" can not be included with "superfences", 73 | // so we include the pieces separately. 74 | "markdown.extensions.smart_strong", 75 | "markdown.extensions.footnotes", 76 | "markdown.extensions.attr_list", 77 | "markdown.extensions.def_list", 78 | "markdown.extensions.tables", 79 | "markdown.extensions.abbr", 80 | // Extra's Markdown parsing in raw HTML cannot be 81 | // included by itself, but "pymdownx" exposes it so we can. 82 | "pymdownx.extrarawhtml", 83 | 84 | // More default Python Markdown extensions 85 | { 86 | "markdown.extensions.toc": 87 | { 88 | "permalink": "\ue157" 89 | } 90 | }, 91 | "markdown.extensions.meta", 92 | "markdown.extensions.sane_lists", 93 | "markdown.extensions.smarty", 94 | "markdown.extensions.wikilinks", 95 | "markdown.extensions.admonition", 96 | 97 | // PyMdown extensions that help give a GitHub-ish feel 98 | "pymdownx.superfences", // Nested fences and UML support 99 | { 100 | "pymdownx.magiclink": { // Auto linkify URLs and email addresses 101 | "repo_url_shortener": true, 102 | "repo_url_shorthand": true 103 | } 104 | }, 105 | "pymdownx.tasklist", // Task lists 106 | { 107 | "pymdownx.tilde": { // Provide ~~delete~~ 108 | "subscript": false 109 | } 110 | }, 111 | { 112 | "pymdownx.emoji": { // Provide GitHub's emojis 113 | "emoji_index": {"!!python/name": "pymdownx.emoji.gemoji"}, 114 | "emoji_generator": {"!!python/name": "pymdownx.emoji.to_png"}, 115 | "alt": "short", 116 | "options": { 117 | "attributes": { 118 | "align": "absmiddle", 119 | "height": "20px", 120 | "width": "20px" 121 | }, 122 | "image_path": "https://assets-cdn.github.com/images/icons/emoji/unicode/", 123 | "non_standard_image_path": "https://assets-cdn.github.com/images/icons/emoji/" 124 | } 125 | } 126 | } 127 | ], 128 | 129 | /* 130 | Enabled parsers for the parser "select parser" command 131 | Available parsers: markdown, github 132 | 133 | When there are more than one parser in the list, Sublime will prompt 134 | via the quick panel for which one to use. If there is only one, it 135 | will automatically run that parser. 136 | */ 137 | "enabled_parsers": ["markdown", "github"], 138 | 139 | /* 140 | Custom external markdown parsers. 141 | 142 | "markdown_binary_map" contains key values pairs. The key 143 | is name of the parser and what is used in "enabled_parsers" 144 | to turn on the access to the parser. The value is an array 145 | containing the path to the binary and all the parameters that 146 | are desired. 147 | 148 | Multimarkdown is provided as an example below. It's path may differ 149 | on your system. 150 | */ 151 | 152 | "markdown_binary_map": { 153 | "multimarkdown": ["/usr/local/bin/multimarkdown"] 154 | }, 155 | 156 | /* 157 | Default mode for the github Markdown parser : markdown (documents) or gfm (comments) 158 | see http://developer.github.com/v3/markdown/#render-an-arbitrary-markdown-document 159 | */ 160 | "github_mode": "markdown", 161 | 162 | /* 163 | Enables a post process to inject header ids to ensure hrefs to headers work 164 | */ 165 | "github_inject_header_ids": false, 166 | 167 | /* 168 | Uses an OAuth token when parsing markdown with GitHub API. To create one for Markdown Preview, see https://help.github.com/articles/creating-an-oauth-token-for-command-line-use. 169 | Warn: this secret *must not be shared* with anyone and at least you should create it with minimal scopes for security reasons. 170 | */ 171 | // "github_oauth_token": "secret", 172 | 173 | /* 174 | Sets the default css file to embed in the HTML 175 | 176 | default - Use the builtin CSS or github CSS, depending on parser config (markdown.css or github.css) 177 | other - Set an absolute path or url to any css file 178 | 179 | Should be an array, but will take a single string to support legacy convention. 180 | */ 181 | "css": ["default"], 182 | 183 | /* 184 | Allow CSS overrides 185 | 186 | true - Any file with matching a .markdown_filetype extension with .css will be loaded as an override 187 | false - Matching files ignored 188 | */ 189 | "allow_css_overrides": true, 190 | 191 | /* 192 | Specify a HTML template file to render your markdown within. 193 | 194 | Available place holders in HTML template: 195 | {{ HEAD }} - would be replaced by generated stylesheets, javascripts enabled above 196 | {{ BODY }} - would be replaced by HTML converted from markdown 197 | 198 | Remove "default" from "css" setting to avoid injecting the default CSS if desired. 199 | 200 | Refer to 'customized-template-sample.html' as a show case. 201 | */ 202 | "html_template": "", 203 | 204 | 205 | /* 206 | Sets the JavaScript files to embed in the HTML 207 | 208 | Set an array of URLs or filepaths to JavaScript files. Absolute filepaths will be loaded 209 | into the script tag; others will be set as the `src` attribute. The order of files in the 210 | array is the order in which they are embedded. 211 | */ 212 | "js": [], 213 | 214 | /* 215 | Enable auto-reloaded on save. Will not work if GitHub parser is used without oauth key specified. 216 | */ 217 | "enable_autoreload": true, 218 | 219 | /* 220 | Sets the supported filetypes for auto-reload on save 221 | */ 222 | "markdown_filetypes": [".md", ".markdown", ".mdown"], 223 | 224 | /* 225 | Sets a custom temporary folder for MarkdownPreview-generated HTML files. Useful if you're 226 | using LiveReload and don't want to use the OS default. The directory will be created if it 227 | doesn't exist. Relative paths are supported, and are checked against `os.path.isabs`, see 228 | doc: http://docs.python.org/3/library/os.path.html#os.path.isabs 229 | 230 | Examples: /tmp/custom_folder (Linux/OSX - absolute path) 231 | C:/TEMP/MYNOTES 232 | C:\\TEMP\\MYNOTES (Windows - absolute path, forward slash or escaped back slash) 233 | build (All OS - relative path, current dir) 234 | ../build (Linux/OSX - relative path, in parent dir) 235 | ..\\build (Windows - relative path, in parent dir) 236 | */ 237 | "path_tempfile": "", 238 | 239 | /* 240 | Sets HTML output to a simple form: 241 | - No head 242 | - No body tags 243 | - ids, classes, and style are stripped out 244 | - Just bare minimum HTML tags and attributes 245 | - extension modifications included 246 | */ 247 | "html_simple": false, 248 | 249 | /* 250 | Sets how image paths are handled. 251 | Setting is a string value: (absolute | relative | base64 | none) 252 | absolute: converts relative local paths to absolute 253 | relative: converts relative local paths to a path relative to the 254 | HTML output 255 | base64: coverts the local file to base64 and embeds it in the HTML 256 | none: does nothing 257 | */ 258 | "image_path_conversion": "absolute", 259 | 260 | /* 261 | Sets how file paths are handled. 262 | Setting is a string value: (absolute | relative | none) 263 | absolute: converts relative local paths to absolute 264 | relative: converts relative local paths to a path relative to the 265 | HTML output 266 | none: does nothing 267 | */ 268 | "file_path_conversions": "absolute", 269 | 270 | /* 271 | Sets how multimarkdown critic marks are handled. 272 | Setting is a string value: (accept | reject | none) 273 | accept: Accepts the proposed inserts and deletions (comments etc. are discarded) 274 | reject: Rejects the proposed inserts and deletions (comments etc. are discarded) 275 | none: does nothing 276 | 277 | Critic marks only affects "github" and "markdown" (Python Markdown). 278 | */ 279 | "strip_critic_marks": "none", 280 | 281 | /* 282 | Strips the YAML front matter header and converts title to a heading 283 | */ 284 | "strip_yaml_front_matter": false, 285 | 286 | /* do we show the panel when building with CMD+B */ 287 | "show_panel_on_build": true, 288 | 289 | /* do we include the CSS when outputting HTML? */ 290 | "include_head": ["build", "browser", "sublime", "clipboard", "save"] 291 | } 292 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sublime Text Markdown Preview 2 | 3 | **New Repository location: https://github.com/facelessuser/MarkdownPreview. Please direct all issues, pulls, and feature requests to the new repository** 4 | 5 | Preview and build your markdown files quickly in your web browser. 6 | 7 | :warning: This project is now maintained here : [facelessuser/MarkdownPreview][home]. 8 | 9 | ## Support 10 | 11 | - Any bugs about Markdown Preview please feel free to report [here][issue]. 12 | 13 | 14 | [home]: https://github.com/facelessuser/MarkdownPreview 15 | [issue]: https://github.com/facelessuser/MarkdownPreview/issues 16 | -------------------------------------------------------------------------------- /css/github.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: octicons-anchor; 3 | src: url(https://cdnjs.cloudflare.com/ajax/libs/octicons/4.4.0/font/octicons.woff) format('woff'); 4 | } 5 | 6 | * { 7 | box-sizing: border-box; 8 | } 9 | 10 | body { 11 | width: 980px; 12 | margin-right: auto; 13 | margin-left: auto; 14 | } 15 | 16 | body .markdown-body { 17 | padding: 45px; 18 | border: 1px solid #ddd; 19 | border-radius: 3px; 20 | word-wrap: break-word; 21 | } 22 | 23 | pre { 24 | font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; 25 | } 26 | 27 | .markdown-body { 28 | -webkit-text-size-adjust: 100%; 29 | text-size-adjust: 100%; 30 | color: #333; 31 | font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 32 | font-size: 16px; 33 | line-height: 1.6; 34 | word-wrap: break-word; 35 | } 36 | 37 | .markdown-body a { 38 | background-color: transparent; 39 | } 40 | 41 | .markdown-body a:active, 42 | .markdown-body a:hover { 43 | outline: 0; 44 | } 45 | 46 | .markdown-body strong { 47 | font-weight: bold; 48 | } 49 | 50 | .markdown-body h1 { 51 | font-size: 2em; 52 | margin: 0.67em 0; 53 | } 54 | 55 | .markdown-body img { 56 | border: 0; 57 | } 58 | 59 | .markdown-body hr { 60 | box-sizing: content-box; 61 | height: 0; 62 | } 63 | 64 | .markdown-body pre { 65 | overflow: auto; 66 | } 67 | 68 | .markdown-body code, 69 | .markdown-body kbd, 70 | .markdown-body pre { 71 | font-family: monospace, monospace; 72 | font-size: 1em; 73 | } 74 | 75 | .markdown-body input { 76 | color: inherit; 77 | font: inherit; 78 | margin: 0; 79 | } 80 | 81 | .markdown-body html input[disabled] { 82 | cursor: default; 83 | } 84 | 85 | .markdown-body input { 86 | line-height: normal; 87 | } 88 | 89 | .markdown-body input[type="checkbox"] { 90 | box-sizing: border-box; 91 | padding: 0; 92 | } 93 | 94 | .markdown-body table { 95 | border-collapse: collapse; 96 | border-spacing: 0; 97 | } 98 | 99 | .markdown-body td, 100 | .markdown-body th { 101 | padding: 0; 102 | } 103 | 104 | .markdown-body input { 105 | font: 13px / 1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 106 | } 107 | 108 | .markdown-body a { 109 | color: #4078c0; 110 | text-decoration: none; 111 | } 112 | 113 | .markdown-body a:hover, 114 | .markdown-body a:active { 115 | text-decoration: underline; 116 | } 117 | 118 | .markdown-body hr { 119 | height: 0; 120 | margin: 15px 0; 121 | overflow: hidden; 122 | background: transparent; 123 | border: 0; 124 | border-bottom: 1px solid #ddd; 125 | } 126 | 127 | .markdown-body hr:before { 128 | display: table; 129 | content: ""; 130 | } 131 | 132 | .markdown-body hr:after { 133 | display: table; 134 | clear: both; 135 | content: ""; 136 | } 137 | 138 | .markdown-body h1, 139 | .markdown-body h2, 140 | .markdown-body h3, 141 | .markdown-body h4, 142 | .markdown-body h5, 143 | .markdown-body h6 { 144 | margin-top: 15px; 145 | margin-bottom: 15px; 146 | line-height: 1.1; 147 | } 148 | 149 | .markdown-body h1 { 150 | font-size: 30px; 151 | } 152 | 153 | .markdown-body h2 { 154 | font-size: 21px; 155 | } 156 | 157 | .markdown-body h3 { 158 | font-size: 16px; 159 | } 160 | 161 | .markdown-body h4 { 162 | font-size: 14px; 163 | } 164 | 165 | .markdown-body h5 { 166 | font-size: 12px; 167 | } 168 | 169 | .markdown-body h6 { 170 | font-size: 11px; 171 | } 172 | 173 | .markdown-body blockquote { 174 | margin: 0; 175 | } 176 | 177 | .markdown-body ul, 178 | .markdown-body ol { 179 | padding: 0; 180 | margin-top: 0; 181 | margin-bottom: 0; 182 | } 183 | 184 | .markdown-body ol ol, 185 | .markdown-body ul ol { 186 | list-style-type: lower-roman; 187 | } 188 | 189 | .markdown-body ul ul ol, 190 | .markdown-body ul ol ol, 191 | .markdown-body ol ul ol, 192 | .markdown-body ol ol ol { 193 | list-style-type: lower-alpha; 194 | } 195 | 196 | .markdown-body dd { 197 | margin-left: 0; 198 | } 199 | 200 | .markdown-body code { 201 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; 202 | font-size: 12px; 203 | } 204 | 205 | .markdown-body pre { 206 | margin-top: 0; 207 | margin-bottom: 0; 208 | font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; 209 | } 210 | 211 | .markdown-body .select::-ms-expand { 212 | opacity: 0; 213 | } 214 | 215 | .markdown-body .octicon { 216 | font: normal normal normal 16px/1 octicons-anchor; 217 | display: inline-block; 218 | text-decoration: none; 219 | text-rendering: auto; 220 | -webkit-font-smoothing: antialiased; 221 | -moz-osx-font-smoothing: grayscale; 222 | -webkit-user-select: none; 223 | -moz-user-select: none; 224 | -ms-user-select: none; 225 | user-select: none; 226 | } 227 | 228 | .markdown-body .octicon-link:before { 229 | content: '\f05c'; 230 | } 231 | 232 | .markdown-body:before { 233 | display: table; 234 | content: ""; 235 | } 236 | 237 | .markdown-body:after { 238 | display: table; 239 | clear: both; 240 | content: ""; 241 | } 242 | 243 | .markdown-body>*:first-child { 244 | margin-top: 0 !important; 245 | } 246 | 247 | .markdown-body>*:last-child { 248 | margin-bottom: 0 !important; 249 | } 250 | 251 | .markdown-body a:not([href]) { 252 | color: inherit; 253 | text-decoration: none; 254 | } 255 | 256 | .markdown-body .anchor { 257 | display: inline-block; 258 | padding-right: 2px; 259 | margin-left: -18px; 260 | } 261 | 262 | .markdown-body .anchor:focus { 263 | outline: none; 264 | } 265 | 266 | .markdown-body h1, 267 | .markdown-body h2, 268 | .markdown-body h3, 269 | .markdown-body h4, 270 | .markdown-body h5, 271 | .markdown-body h6 { 272 | margin-top: 1em; 273 | margin-bottom: 16px; 274 | font-weight: bold; 275 | line-height: 1.4; 276 | } 277 | 278 | .markdown-body h1 .octicon-link, 279 | .markdown-body h2 .octicon-link, 280 | .markdown-body h3 .octicon-link, 281 | .markdown-body h4 .octicon-link, 282 | .markdown-body h5 .octicon-link, 283 | .markdown-body h6 .octicon-link { 284 | color: #000; 285 | vertical-align: middle; 286 | visibility: hidden; 287 | } 288 | 289 | .markdown-body h1:hover .anchor, 290 | .markdown-body h2:hover .anchor, 291 | .markdown-body h3:hover .anchor, 292 | .markdown-body h4:hover .anchor, 293 | .markdown-body h5:hover .anchor, 294 | .markdown-body h6:hover .anchor { 295 | text-decoration: none; 296 | } 297 | 298 | .markdown-body h1:hover .anchor .octicon-link, 299 | .markdown-body h2:hover .anchor .octicon-link, 300 | .markdown-body h3:hover .anchor .octicon-link, 301 | .markdown-body h4:hover .anchor .octicon-link, 302 | .markdown-body h5:hover .anchor .octicon-link, 303 | .markdown-body h6:hover .anchor .octicon-link { 304 | visibility: visible; 305 | } 306 | 307 | .markdown-body h1 { 308 | padding-bottom: 0.3em; 309 | font-size: 2.25em; 310 | line-height: 1.2; 311 | border-bottom: 1px solid #eee; 312 | } 313 | 314 | .markdown-body h1 .anchor { 315 | line-height: 1; 316 | } 317 | 318 | .markdown-body h2 { 319 | padding-bottom: 0.3em; 320 | font-size: 1.75em; 321 | line-height: 1.225; 322 | border-bottom: 1px solid #eee; 323 | } 324 | 325 | .markdown-body h2 .anchor { 326 | line-height: 1; 327 | } 328 | 329 | .markdown-body h3 { 330 | font-size: 1.5em; 331 | line-height: 1.43; 332 | } 333 | 334 | .markdown-body h3 .anchor { 335 | line-height: 1.2; 336 | } 337 | 338 | .markdown-body h4 { 339 | font-size: 1.25em; 340 | } 341 | 342 | .markdown-body h4 .anchor { 343 | line-height: 1.2; 344 | } 345 | 346 | .markdown-body h5 { 347 | font-size: 1em; 348 | } 349 | 350 | .markdown-body h5 .anchor { 351 | line-height: 1.1; 352 | } 353 | 354 | .markdown-body h6 { 355 | font-size: 1em; 356 | color: #777; 357 | } 358 | 359 | .markdown-body h6 .anchor { 360 | line-height: 1.1; 361 | } 362 | 363 | .markdown-body p, 364 | .markdown-body blockquote, 365 | .markdown-body ul, 366 | .markdown-body ol, 367 | .markdown-body dl, 368 | .markdown-body table, 369 | .markdown-body pre { 370 | margin-top: 0; 371 | margin-bottom: 16px; 372 | } 373 | 374 | .markdown-body hr { 375 | height: 4px; 376 | padding: 0; 377 | margin: 16px 0; 378 | background-color: #e7e7e7; 379 | border: 0 none; 380 | } 381 | 382 | .markdown-body ul, 383 | .markdown-body ol { 384 | padding-left: 2em; 385 | } 386 | 387 | .markdown-body ul ul, 388 | .markdown-body ul ol, 389 | .markdown-body ol ol, 390 | .markdown-body ol ul { 391 | margin-top: 0; 392 | margin-bottom: 0; 393 | } 394 | 395 | .markdown-body li>p { 396 | margin-top: 16px; 397 | } 398 | 399 | .markdown-body dl { 400 | padding: 0; 401 | } 402 | 403 | .markdown-body dl dt { 404 | padding: 0; 405 | margin-top: 16px; 406 | font-size: 1em; 407 | font-style: italic; 408 | font-weight: bold; 409 | } 410 | 411 | .markdown-body dl dd { 412 | padding: 0 16px; 413 | margin-bottom: 16px; 414 | } 415 | 416 | .markdown-body blockquote { 417 | padding: 0 15px; 418 | color: #777; 419 | border-left: 4px solid #ddd; 420 | } 421 | 422 | .markdown-body blockquote>:first-child { 423 | margin-top: 0; 424 | } 425 | 426 | .markdown-body blockquote>:last-child { 427 | margin-bottom: 0; 428 | } 429 | 430 | .markdown-body table { 431 | display: block; 432 | width: 100%; 433 | overflow: auto; 434 | word-break: normal; 435 | word-break: keep-all; 436 | } 437 | 438 | .markdown-body table th { 439 | font-weight: bold; 440 | } 441 | 442 | .markdown-body table th, 443 | .markdown-body table td { 444 | padding: 6px 13px; 445 | border: 1px solid #ddd; 446 | } 447 | 448 | .markdown-body table tr { 449 | background-color: #fff; 450 | border-top: 1px solid #ccc; 451 | } 452 | 453 | .markdown-body table tr:nth-child(2n) { 454 | background-color: #f8f8f8; 455 | } 456 | 457 | .markdown-body img { 458 | max-width: 100%; 459 | box-sizing: content-box; 460 | background-color: #fff; 461 | } 462 | 463 | .markdown-body code { 464 | padding: 0; 465 | padding-top: 0.2em; 466 | padding-bottom: 0.2em; 467 | margin: 0; 468 | font-size: 85%; 469 | background-color: rgba(0,0,0,0.04); 470 | border-radius: 3px; 471 | } 472 | 473 | .markdown-body code:before, 474 | .markdown-body code:after { 475 | letter-spacing: -0.2em; 476 | content: "\00a0"; 477 | } 478 | 479 | .markdown-body pre>code { 480 | padding: 0; 481 | margin: 0; 482 | font-size: 100%; 483 | word-break: normal; 484 | white-space: pre; 485 | background: transparent; 486 | border: 0; 487 | } 488 | 489 | .markdown-body .highlight { 490 | margin-bottom: 16px; 491 | } 492 | 493 | .markdown-body .highlight pre, 494 | .markdown-body pre { 495 | padding: 16px; 496 | overflow: auto; 497 | font-size: 85%; 498 | line-height: 1.45; 499 | background-color: #f7f7f7; 500 | border-radius: 3px; 501 | } 502 | 503 | .markdown-body .highlight pre { 504 | margin-bottom: 0; 505 | word-break: normal; 506 | } 507 | 508 | .markdown-body pre { 509 | word-wrap: normal; 510 | } 511 | 512 | .markdown-body pre code { 513 | display: inline; 514 | max-width: initial; 515 | padding: 0; 516 | margin: 0; 517 | overflow: initial; 518 | line-height: inherit; 519 | word-wrap: normal; 520 | background-color: transparent; 521 | border: 0; 522 | } 523 | 524 | .markdown-body pre code:before, 525 | .markdown-body pre code:after { 526 | content: normal; 527 | } 528 | 529 | .markdown-body kbd { 530 | display: inline-block; 531 | padding: 3px 5px; 532 | font-size: 11px; 533 | line-height: 10px; 534 | color: #555; 535 | vertical-align: middle; 536 | background-color: #fcfcfc; 537 | border: solid 1px #ccc; 538 | border-bottom-color: #bbb; 539 | border-radius: 3px; 540 | box-shadow: inset 0 -1px 0 #bbb; 541 | } 542 | 543 | .markdown-body .pl-c { 544 | color: #969896; 545 | } 546 | 547 | .markdown-body .pl-c1, 548 | .markdown-body .pl-s .pl-v { 549 | color: #0086b3; 550 | } 551 | 552 | .markdown-body .pl-e, 553 | .markdown-body .pl-en { 554 | color: #795da3; 555 | } 556 | 557 | .markdown-body .pl-s .pl-s1, 558 | .markdown-body .pl-smi { 559 | color: #333; 560 | } 561 | 562 | .markdown-body .pl-ent { 563 | color: #63a35c; 564 | } 565 | 566 | .markdown-body .pl-k { 567 | color: #a71d5d; 568 | } 569 | 570 | .markdown-body .pl-pds, 571 | .markdown-body .pl-s, 572 | .markdown-body .pl-s .pl-pse .pl-s1, 573 | .markdown-body .pl-sr, 574 | .markdown-body .pl-sr .pl-cce, 575 | .markdown-body .pl-sr .pl-sra, 576 | .markdown-body .pl-sr .pl-sre { 577 | color: #183691; 578 | } 579 | 580 | .markdown-body .pl-v { 581 | color: #ed6a43; 582 | } 583 | 584 | .markdown-body .pl-id { 585 | color: #b52a1d; 586 | } 587 | 588 | .markdown-body .pl-ii { 589 | background-color: #b52a1d; 590 | color: #f8f8f8; 591 | } 592 | 593 | .markdown-body .pl-sr .pl-cce { 594 | color: #63a35c; 595 | font-weight: bold; 596 | } 597 | 598 | .markdown-body .pl-ml { 599 | color: #693a17; 600 | } 601 | 602 | .markdown-body .pl-mh, 603 | .markdown-body .pl-mh .pl-en, 604 | .markdown-body .pl-ms { 605 | color: #1d3e81; 606 | font-weight: bold; 607 | } 608 | 609 | .markdown-body .pl-mq { 610 | color: #008080; 611 | } 612 | 613 | .markdown-body .pl-mi { 614 | color: #333; 615 | font-style: italic; 616 | } 617 | 618 | .markdown-body .pl-mb { 619 | color: #333; 620 | font-weight: bold; 621 | } 622 | 623 | .markdown-body .pl-md { 624 | background-color: #ffecec; 625 | color: #bd2c00; 626 | } 627 | 628 | .markdown-body .pl-mi1 { 629 | background-color: #eaffea; 630 | color: #55a532; 631 | } 632 | 633 | .markdown-body .pl-mdr { 634 | color: #795da3; 635 | font-weight: bold; 636 | } 637 | 638 | .markdown-body .pl-mo { 639 | color: #1d3e81; 640 | } 641 | 642 | .markdown-body kbd { 643 | display: inline-block; 644 | padding: 3px 5px; 645 | font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; 646 | line-height: 10px; 647 | color: #555; 648 | vertical-align: middle; 649 | background-color: #fcfcfc; 650 | border: solid 1px #ccc; 651 | border-bottom-color: #bbb; 652 | border-radius: 3px; 653 | box-shadow: inset 0 -1px 0 #bbb; 654 | } 655 | 656 | .markdown-body .plan-price-unit { 657 | color: #767676; 658 | font-weight: normal; 659 | } 660 | 661 | .markdown-body .task-list-item { 662 | list-style-type: none; 663 | } 664 | 665 | .markdown-body .task-list-item+.task-list-item { 666 | margin-top: 3px; 667 | } 668 | 669 | .markdown-body .task-list-item input { 670 | margin: 0 0.35em 0.25em -1.6em; 671 | vertical-align: middle; 672 | } 673 | 674 | .markdown-body .plan-choice { 675 | padding: 15px; 676 | padding-left: 40px; 677 | display: block; 678 | border: 1px solid #e0e0e0; 679 | position: relative; 680 | font-weight: normal; 681 | background-color: #fafafa; 682 | } 683 | 684 | .markdown-body .plan-choice.open { 685 | background-color: #fff; 686 | } 687 | 688 | .markdown-body .plan-choice.open .plan-choice-seat-breakdown { 689 | display: block; 690 | } 691 | 692 | .markdown-body .plan-choice-free { 693 | border-radius: 3px 3px 0 0; 694 | } 695 | 696 | .markdown-body .plan-choice-paid { 697 | border-radius: 0 0 3px 3px; 698 | border-top: 0; 699 | margin-bottom: 20px; 700 | } 701 | 702 | .markdown-body .plan-choice-radio { 703 | position: absolute; 704 | left: 15px; 705 | top: 18px; 706 | } 707 | 708 | .markdown-body .plan-choice-exp { 709 | color: #999; 710 | font-size: 12px; 711 | margin-top: 5px; 712 | } 713 | 714 | .markdown-body .plan-choice-seat-breakdown { 715 | margin-top: 10px; 716 | display: none; 717 | } 718 | 719 | .markdown-body :checked+.radio-label { 720 | z-index: 1; 721 | position: relative; 722 | border-color: #4078c0; 723 | } 724 | 725 | @media print { 726 | body .markdown-body { 727 | padding: 0; 728 | border: none; 729 | } 730 | } 731 | -------------------------------------------------------------------------------- /css/markdown.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 980px; 3 | border: 1px solid #ddd; 4 | outline: 1300px solid #fff; 5 | margin: 16px auto; 6 | } 7 | 8 | body .markdown-body 9 | { 10 | padding: 45px; 11 | } 12 | 13 | @font-face { 14 | font-family: fontawesome-mini; 15 | src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAABE0AA8AAAAAHWwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABWAAAADsAAABUIIslek9TLzIAAAGUAAAAQwAAAFY3d1HZY21hcAAAAdgAAACqAAACOvWLi0FjdnQgAAAChAAAABMAAAAgBtX/BGZwZ20AAAKYAAAFkAAAC3CKkZBZZ2FzcAAACCgAAAAIAAAACAAAABBnbHlmAAAIMAAABdQAAAjkYT9TNWhlYWQAAA4EAAAAMwAAADYQ6WvNaGhlYQAADjgAAAAfAAAAJAc6A1pobXR4AAAOWAAAACAAAAA0Kmz/7mxvY2EAAA54AAAAHAAAABwQPBJubWF4cAAADpQAAAAgAAAAIAEHC/NuYW1lAAAOtAAAAYQAAALxhQT4h3Bvc3QAABA4AAAAfgAAAMS3SYh9cHJlcAAAELgAAAB6AAAAhuVBK7x4nGNgZGBg4GIwYLBjYHJx8wlh4MtJLMljkGJgYYAAkDwymzEnMz2RgQPGA8qxgGkOIGaDiAIAJjsFSAB4nGNgZHZmnMDAysDAVMW0h4GBoQdCMz5gMGRkAooysDIzYAUBaa4pDA4Pwz+yMwf9z2KIYg5imAYUZgTJAQDcoQvQAHic7ZHNDYJAFIRnBXf94cDRIiyCKkCpwFCPJ092RcKNDoYKcN4+EmMPvpdvk539zQyAPYBCXEUJhBcCrJ5SQ9YLnLJe4qF5rdb+uWPDngNHTkta101pNyWa8lMhn6xx2dqUnW4q9YOIhAOOeueMSgsR/6ry+P7O5s6xVNg4chBsHUuFnWNJ8uZYwrw7chrsHXkODo7cB0dHOYCTY8kv0VE2WJKD6gOlWjsxAAB4nGNgQAMSEMgc9D8LhAESbAPdAHicrVZpd9NGFB15SZyELCULLWphxMRpsEYmbMGACUGyYyBdnK2VoIsUO+m+8Ynf4F/zZNpz6Dd+Wu8bLySQtOdwmpOjd+fN1czbZRJaktgL65GUmy/F1NYmjew8CemGTctRfCg7eyFlisnfBVEQrZbatx2HREQiULWusEQQ+x5ZmmR86FFGy7akV03KLT3pLlvjQb1V334aOsqxO6GkZjN0aD2yJVUYVaJIpj1S0qZlqPorSSu8v8LMV81QwohOImm8GcbQSN4bZ7TKaDW24yiKbLLcKFIkmuFBFHmU1RLn5IoJDMoHzZDyyqcR5cP8iKzYo5xWsEu20/y+L3mndzk/sV9vUbbkQB/Ijuzg7HQlX4RbW2HctJPtKFQRdtd3QmzZ7FT/Zo/ymkYDtysyvdCMYKl8hRArP6HM/iFZLZxP+ZJHo1qykRNB62VO7Es+gdbjiClxzRhZ0N3RCRHU/ZIzDPaYPh788d4plgsTAngcy3pHJZwIEylhczRJ2jByYCVliyqp9a6YOOV1WsRbwn7t2tGXzmjjUHdiPFsPHVs5UcnxaFKnmUyd2knNoykNopR0JnjMrwMoP6JJXm1jNYmVR9M4ZsaERCICLdxLU0EsO7GkKQTNoxm9uRumuXYtWqTJA/Xco/f05la4udNT2g70s0Z/VqdiOtgL0+lp5C/xadrlIkXp+ukZfkziQdYCMpEtNsOUgwdv/Q7Sy9eWHIXXBtju7fMrqH3WRPCkAfsb0B5P1SkJTIWYVYhWQGKta1mWydWsFqnI1HdDmla+rNMEinIcF8e+jHH9XzMzlpgSvt+J07MjLj1z7UsI0xx8m3U9mtepxXIBcWZ5TqdZlu/rNMfyA53mWZ7X6QhLW6ejLD/UaYHlRzodY3lBC5p038GQizDkAg6QMISlA0NYXoIhLBUMYbkIQ1gWYQjLJRjC8mMYwnIZhrC8rGXV1FNJ49qZWAZsQmBijh65zEXlaiq5VEK7aFRqQ54SbpVUFM+qf2WgXjzyhjmwFkiXyJpfMc6Vj0bl+NYVLW8aO1fAsepvH472OfFS1ouFPwX/1dZUJb1izcOTq/Abhp5sJ6o2qXh0TZfPVT26/l9UVFgL9BtIhVgoyrJscGcihI86nYZqoJVDzGzMPLTrdcuan8P9NzFCFlD9+DcUGgvcg05ZSVnt4KzV19uy3DuDcjgTLEkxN/P6VvgiI7PSfpFZyp6PfB5wBYxKZdhqA60VvNknMQ+Z3iTPBHFbUTZI2tjOBIkNHPOAefOdBCZh6qoN5E7hhg34BWFuwXknXKJ6oyyH7kXs8yik/Fun4kT2qGiMwLPZG2Gv70LKb3EMJDT5pX4MVBWhqRg1FdA0Um6oBl/G2bptQsYO9CMqdsOyrOLDxxb3lZJtGYR8pIjVo6Of1l6iTqrcfmYUl++dvgXBIDUxf3vfdHGQyrtayTJHbQNTtxqVU9eaQ+NVh+rmUfW94+wTOWuabronHnpf06rbwcVcLLD2bQ7SUiYX1PVhhQ2iy8WlUOplNEnvuAcYFhjQ71CKjf+r+th8nitVhdFxJN9O1LfR52AM/A/Yf0f1A9D3Y+hyDS7P95oTn2704WyZrqIX66foNzBrrblZugbc0HQD4iFHrY64yg18pwZxeqS5HOkh4GPdFeIBwCaAxeAT3bWM5lMAo/mMOT7A58xh0GQOgy3mMNhmzhrADnMY7DKHwR5zGHzBnHWAL5nDIGQOg4g5DJ4wJwB4yhwGXzGHwdfMYfANc+4DfMscBjFzGCTMYbCv6dYwzC1e0F2gtkFVoANTT1jcw+JQU2XI/o4Xhv29Qcz+wSCm/qjp9pD6Ey8M9WeDmPqLQUz9VdOdIfU3Xhjq7wYx9Q+DmPpMvxjLZQa/jHyXCgeUXWw+5++J9w/bxUC5AAEAAf//AA94nIVVX2hbZRQ/5/t7893s5ja9f7ouzdZ0TTqz3bRJmogbWya6bG6Cq0VbSV2ddIJjFtfIQHEig80Hda8yUN/0YQz8AyriiyD+xQd92R4HCnaCb3samnpumrpsCsLlfPf7zvedc37nL3CAtc/5W/wQZGA3tOBSY/g+TMjHmwzEoM1Q8+ZjRZY4oJhmBw5/YB6Za0yC5AkhlwA1A1yCBIBOwCII0Cj0U8BAMdUCzq05sKwkP7SlUY6fcJk4Fb/RyE79/6P5hjM/F4aZiXBoeMgzcqQ4Xi1hPqfDLG5FT+lchCVU3lYMyvuwhl1mqndQL0RsuloLywHtthLXI06OblTrhfWVnpSJ5+mwu/JdbtuN3IAnkW0LLMcRwaC7ktrlzridM6kVdyf9uO1UNBByI7JhwtG2sEwab07ORBeilWhqavJCqV0qzZTOl/7ZXQ5TbTcdcFelyGhhRDAQpdqp1FEX3w3cFTc1k9pJQkmm4ySCbSikxRP2QOfN+0tHS5MrpQuTU1Mk5nw0E5Xa0WvrOwDyGax9yB9ma6DAg82wHc43SAGTI4GjBWebOePAERFE8/AHaQpZASSTy8A4WwZiLQMQ82mFKATO0ILicRAoDm9p5P99E5b/fXG+kQYY3TYUuqmERWYoT0u/GNYL2q/4WB3LaVS+VynXsVYIcWw6DkCh3nX1D+VzlYN4LClF5yexSQos8exqZ3KVP+wtrC54u4Nznq6cq+xpMpUUnZ8FUYzE86ud0g28NOIv3Gj5/rmA3ABs7S/ywzFuQ4qyd6QxfNtiQIaEgp3w/entQg4Vcbqa16M5FfpeUB8t1+qeg7mI7cUyOe79wOk86gSxkVec4KPTX69++5x68Yubn5/F+w52z7u08sJX7fZXv8ekT/d2mILJxq6sn+SC6qEJknzLJCxyZEKwWVqYmAPBxBE/9DLeZiWHu7lcr/VytrCRuHojncNuTt9h46tmacmYisnSamdN2bZptcsmSysdVsy1PrOvOzF3xN64Rb937t/og9KHxYdcjIUqFAmIAHGHNzlns+RTPgeUYAQm9DwpNxfxbhhBHPaw3/gfTcXO2L+eJVIx5nsyGkvm9X4/f+bGkH45G0PaSjcMXTjcZyTvi3UdHoCDjQd3IDUVsgwYmUoJK/gp4JJxeRI0MKHZIkgynyIBqBTOUs6rOVCojvjZ4mCQz49ZMlMcp8QoYk6NoBfsxnJtsBohpa8iGJS+ZH7gU7NxME6cmF+t7cO9vB8d3jTWSct0ycW9ranXmolNDwmVkNnxe+8JtoztwS5rKJ0xWS95tQ/1zMYzg69MzUZnNtl1ofNbsml/OJm6f9wjRjpnu2o4MzHzn77IQkRd+1DjwMQ2pqSjGMMhyjrgTbBAKksuUm0iU7hI0aN2wOKOq7WYBSH0HGihj/jkiPxAfmwsEbfYrjMG+j3ij932Db/LV7I/xruNrhnroxjR9HRMb2nTvO0ZXOoHPk8H2ZhDPx93qcE/53sH5np/dkIP7zzhTVKdR/BAY/9ElkkR+A6lJGsqpJ4oQcTxpvBT3Kn58VkaJjgHyPEIws57xkaHh9KuVpDEpJZeMbZ5w/zBHi5NMQ4r5VphsFqID7TyB9eR4pX216c3AHxpdAwoqU9qg0ZJ6yVLKmMSz1iG2z27ifx18NkY0LPx1W/wCc2l5LrznrIsiKsqbmB78A9wIGx4tI8rjihVHJyY9pgMirenVq0yWg7Iw7eogG7ZgYM3qR9959A/fZkg6MnD/exlkmc+jWV4SB15XUR+eqC6l6ZmgPtN9z5JMfik05OV8ljylunJ4J+wA/FUaQSSKotsYsCWqaPBidBLcxkWx7XKFRIb45TGaEhjlF9uUVPqXOtcIwsXbBvfoZXIyRYFdkfnqjExH98xpnPczqzjX/uNdO1Y17Wpi5+6Ts8BXtjVFasp9KZ1mOiNbH65c5w6HgmyF2jFCZywM8mWjRc7T5Pmt0lRy7Y71+jYbpGyvwG4sH0XeJxjYGRgYADiwBB/53h+m68M3MwvgCIM1z5N/g6j///9v5H5BbMnkMvBwAQSBQCIcA9gAHicY2BkYGAO+p8FJF/8//v/F/MLBqAICuAFALYQB5kAeJxjfsHAwLwAiCNB+P9fbJjJmoGBMRUo/wKCAfO2EnQAAAAAANoBXgGcAgICVALaA1IDvAPkBAYEPARyAAEAAAANAF0ABAAAAAAAAgAUACQAcwAAAG4LcAAAAAB4nHWRzWrCQBSFT+pPqUIXLXTTzayKUohGKIibCoLuhbrrYtTRxCYZmYyKyz5Fd32HvlDfoO/QkziIFJtw9bvnnpl7ZwLgBt/wcHieGAf2UGd24Atcou+4RH3kuEweO66QXx1XyaHjGh6ROa7jFp/cwStfMVvhy7GHO+/e8QWuvcBxifqz4zL5xXGF/Oa4Sn53XMPE+3Bcx4P3M9DrvYmWoRWNQVN02kFXTPdCU4pSGQu5saE2meiLhU6timPtz3SSs9ypTCdqrJabWJoT5QQnymSRTkXgt0/UkUqVkVbN807ZdtmxdiEWRidi6HqItdErNbN+aO2612qd9sYAGmvsYRBhyUu0EGhQbfK/gzYCdElTOgSdB1eEFBIxFYkNV4RFJWPeZyyYpVQVHTHZx4y/yVGX2LGWFZri51TccUOn5B7nPefVCSPvGhVVwUl9znveO2KkhV8Wk82PZ8qwZf8OVcu1+fSmWCMw/HMOwXvKaysqM+p+cVuWag8tvv+c+xdd+4+teJxtjUEOwiAURJla24KliQfhUA2g/Sl+CKXx+loNrpzVezOLEY34Ron/0WhwQoszOvQYIKFwwQiNSbSBeO2SZ0tBP4j3zVjKNng32ZmtD1VVXCuOiw/pJ8S3WOU6l+K5UOTaDC4+2TjKMtN9KQf1ezLx/Sg/00FCvABHhjDjAAB4nGPw3sFwIihiIyNjX+QGxp0cDBwMyQUbGVidNjEwMmiBGJu5mBg5ICw+BjCLzWkX0wGgNCeQze60i8EBwmZmcNmowtgRGLHBoSNiI3OKy0Y1EG8XRwMDI4tDR3JIBEhJJBBs5mFi5NHawfi/dQNL70YmBhcADHYj9AAA) format('woff'); 16 | } 17 | 18 | .markdown-body { 19 | font-family: sans-serif; 20 | -ms-text-size-adjust: 100%; 21 | -webkit-text-size-adjust: 100%; 22 | color: #333333; 23 | overflow: hidden; 24 | font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; 25 | font-size: 16px; 26 | line-height: 1.6; 27 | word-wrap: break-word; 28 | } 29 | 30 | .markdown-body a { 31 | background: transparent; 32 | } 33 | 34 | .markdown-body a:active, 35 | .markdown-body a:hover { 36 | outline: 0; 37 | } 38 | 39 | .markdown-body b, 40 | .markdown-body strong { 41 | font-weight: bold; 42 | } 43 | 44 | .markdown-body mark { 45 | background: #ff0; 46 | color: #000; 47 | font-style: italic; 48 | font-weight: bold; 49 | } 50 | 51 | .markdown-body sub, 52 | .markdown-body sup { 53 | font-size: 75%; 54 | line-height: 0; 55 | position: relative; 56 | vertical-align: baseline; 57 | } 58 | .markdown-body sup { 59 | top: -0.5em; 60 | } 61 | .markdown-body sub { 62 | bottom: -0.25em; 63 | } 64 | 65 | .markdown-body h1 { 66 | font-size: 2em; 67 | margin: 0.67em 0; 68 | } 69 | 70 | .markdown-body img { 71 | border: 0; 72 | } 73 | 74 | .markdown-body hr { 75 | -moz-box-sizing: content-box; 76 | box-sizing: content-box; 77 | height: 0; 78 | } 79 | 80 | .markdown-body pre { 81 | overflow: auto; 82 | } 83 | 84 | .markdown-body code, 85 | .markdown-body kbd, 86 | .markdown-body pre, 87 | .markdown-body samp { 88 | font-family: monospace, monospace; 89 | font-size: 1em; 90 | } 91 | 92 | .markdown-body input { 93 | color: inherit; 94 | font: inherit; 95 | margin: 0; 96 | } 97 | 98 | .markdown-body html input[disabled] { 99 | cursor: default; 100 | } 101 | 102 | .markdown-body input { 103 | line-height: normal; 104 | } 105 | 106 | .markdown-body input[type="checkbox"] { 107 | box-sizing: border-box; 108 | padding: 0; 109 | } 110 | 111 | .markdown-body table { 112 | border-collapse: collapse; 113 | border-spacing: 0; 114 | } 115 | 116 | .markdown-body td, 117 | .markdown-body th { 118 | padding: 0; 119 | } 120 | 121 | .markdown-body .codehilitetable { 122 | border: 0; 123 | border-spacing: 0; 124 | } 125 | 126 | .markdown-body .codehilitetable tr { 127 | border: 0; 128 | } 129 | 130 | .markdown-body .codehilitetable pre, 131 | .markdown-body .codehilitetable div.codehilite { 132 | margin: 0; 133 | } 134 | 135 | .markdown-body .linenos, 136 | .markdown-body .code, 137 | .markdown-body .codehilitetable td { 138 | border: 0; 139 | padding: 0; 140 | } 141 | 142 | .markdown-body td:not(.linenos) .linenodiv { 143 | padding: 0 !important; 144 | } 145 | 146 | .markdown-body .code { 147 | width: 100%; 148 | } 149 | 150 | .markdown-body .linenos div pre, 151 | .markdown-body .linenodiv pre, 152 | .markdown-body .linenodiv { 153 | border: 0; 154 | -webkit-border-radius: 0; 155 | -moz-border-radius: 0; 156 | border-radius: 0; 157 | -webkit-border-top-left-radius: 3px; 158 | -webkit-border-bottom-left-radius: 3px; 159 | -moz-border-radius-topleft: 3px; 160 | -moz-border-radius-bottomleft: 3px; 161 | border-top-left-radius: 3px; 162 | border-bottom-left-radius: 3px; 163 | } 164 | 165 | .markdown-body .code div pre, 166 | .markdown-body .code div { 167 | border: 0; 168 | -webkit-border-radius: 0; 169 | -moz-border-radius: 0; 170 | border-radius: 0; 171 | -webkit-border-top-right-radius: 3px; 172 | -webkit-border-bottom-right-radius: 3px; 173 | -moz-border-radius-topright: 3px; 174 | -moz-border-radius-bottomright: 3px; 175 | border-top-right-radius: 3px; 176 | border-bottom-right-radius: 3px; 177 | } 178 | 179 | .markdown-body * { 180 | -moz-box-sizing: border-box; 181 | box-sizing: border-box; 182 | } 183 | 184 | .markdown-body input { 185 | font: 13px Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"; 186 | line-height: 1.4; 187 | } 188 | 189 | .markdown-body a { 190 | color: #4183c4; 191 | text-decoration: none; 192 | } 193 | 194 | .markdown-body a:hover, 195 | .markdown-body a:focus, 196 | .markdown-body a:active { 197 | text-decoration: underline; 198 | } 199 | 200 | .markdown-body hr { 201 | height: 0; 202 | margin: 15px 0; 203 | overflow: hidden; 204 | background: transparent; 205 | border: 0; 206 | border-bottom: 1px solid #ddd; 207 | } 208 | 209 | .markdown-body hr:before, 210 | .markdown-body hr:after { 211 | display: table; 212 | content: " "; 213 | } 214 | 215 | .markdown-body hr:after { 216 | clear: both; 217 | } 218 | 219 | .markdown-body h1, 220 | .markdown-body h2, 221 | .markdown-body h3, 222 | .markdown-body h4, 223 | .markdown-body h5, 224 | .markdown-body h6 { 225 | margin-top: 15px; 226 | margin-bottom: 15px; 227 | line-height: 1.1; 228 | } 229 | 230 | .markdown-body h1 { 231 | font-size: 30px; 232 | } 233 | 234 | .markdown-body h2 { 235 | font-size: 21px; 236 | } 237 | 238 | .markdown-body h3 { 239 | font-size: 16px; 240 | } 241 | 242 | .markdown-body h4 { 243 | font-size: 14px; 244 | } 245 | 246 | .markdown-body h5 { 247 | font-size: 12px; 248 | } 249 | 250 | .markdown-body h6 { 251 | font-size: 11px; 252 | } 253 | 254 | .markdown-body blockquote { 255 | margin: 0; 256 | } 257 | 258 | .markdown-body ul, 259 | .markdown-body ol { 260 | padding: 0; 261 | margin-top: 0; 262 | margin-bottom: 0; 263 | } 264 | 265 | .markdown-body ol ol, 266 | .markdown-body ul ol { 267 | list-style-type: lower-roman; 268 | } 269 | 270 | .markdown-body ul ul ol, 271 | .markdown-body ul ol ol, 272 | .markdown-body ol ul ol, 273 | .markdown-body ol ol ol { 274 | list-style-type: lower-alpha; 275 | } 276 | 277 | .markdown-body dd { 278 | margin-left: 0; 279 | } 280 | 281 | .markdown-body code, 282 | .markdown-body pre, 283 | .markdown-body samp { 284 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; 285 | font-size: 12px; 286 | } 287 | 288 | .markdown-body pre { 289 | margin-top: 0; 290 | margin-bottom: 0; 291 | } 292 | 293 | .markdown-body kbd { 294 | background-color: #e7e7e7; 295 | background-image: -moz-linear-gradient(#fefefe, #e7e7e7); 296 | background-image: -webkit-linear-gradient(#fefefe, #e7e7e7); 297 | background-image: linear-gradient(#fefefe, #e7e7e7); 298 | background-repeat: repeat-x; 299 | border-radius: 2px; 300 | border: 1px solid #cfcfcf; 301 | color: #000; 302 | padding: 3px 5px; 303 | line-height: 10px; 304 | font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; 305 | display: inline-block; 306 | } 307 | 308 | .markdown-body>*:first-child { 309 | margin-top: 0 !important; 310 | } 311 | 312 | .markdown-body>*:last-child { 313 | margin-bottom: 0 !important; 314 | } 315 | 316 | .markdown-body .headerlink { 317 | font: normal 400 16px fontawesome-mini; 318 | vertical-align: middle; 319 | margin-left: -16px; 320 | float: left; 321 | display: inline-block; 322 | text-decoration: none; 323 | opacity: 0; 324 | color: #333; 325 | } 326 | 327 | .markdown-body .headerlink:focus { 328 | outline: none; 329 | } 330 | 331 | .markdown-body h1 .headerlink { 332 | margin-top: 0.8rem; 333 | } 334 | 335 | .markdown-body h2 .headerlink, 336 | .markdown-body h3 .headerlink { 337 | margin-top: 0.6rem; 338 | } 339 | 340 | .markdown-body h4 .headerlink { 341 | margin-top: 0.2rem; 342 | } 343 | 344 | .markdown-body h5 .headerlink, 345 | .markdown-body h6 .headerlink { 346 | margin-top: 0; 347 | } 348 | 349 | .markdown-body .headerlink:hover, 350 | .markdown-body h1:hover .headerlink, 351 | .markdown-body h2:hover .headerlink, 352 | .markdown-body h3:hover .headerlink, 353 | .markdown-body h4:hover .headerlink, 354 | .markdown-body h5:hover .headerlink, 355 | .markdown-body h6:hover .headerlink { 356 | opacity: 1; 357 | text-decoration: none; 358 | } 359 | 360 | .markdown-body h1 { 361 | padding-bottom: 0.3em; 362 | font-size: 2.25em; 363 | line-height: 1.2; 364 | border-bottom: 1px solid #eee; 365 | } 366 | 367 | .markdown-body h2 { 368 | padding-bottom: 0.3em; 369 | font-size: 1.75em; 370 | line-height: 1.225; 371 | border-bottom: 1px solid #eee; 372 | } 373 | 374 | .markdown-body h3 { 375 | font-size: 1.5em; 376 | line-height: 1.43; 377 | } 378 | 379 | .markdown-body h4 { 380 | font-size: 1.25em; 381 | } 382 | 383 | .markdown-body h5 { 384 | font-size: 1em; 385 | } 386 | 387 | .markdown-body h6 { 388 | font-size: 1em; 389 | color: #777; 390 | } 391 | 392 | .markdown-body p, 393 | .markdown-body blockquote, 394 | .markdown-body ul, 395 | .markdown-body ol, 396 | .markdown-body dl, 397 | .markdown-body table, 398 | .markdown-body pre, 399 | .markdown-body .admonition { 400 | margin-top: 0; 401 | margin-bottom: 16px; 402 | } 403 | 404 | .markdown-body hr { 405 | height: 4px; 406 | padding: 0; 407 | margin: 16px 0; 408 | background-color: #e7e7e7; 409 | border: 0 none; 410 | } 411 | 412 | .markdown-body ul, 413 | .markdown-body ol { 414 | padding-left: 2em; 415 | } 416 | 417 | .markdown-body ul ul, 418 | .markdown-body ul ol, 419 | .markdown-body ol ol, 420 | .markdown-body ol ul { 421 | margin-top: 0; 422 | margin-bottom: 0; 423 | } 424 | 425 | .markdown-body li>p { 426 | margin-top: 16px; 427 | } 428 | 429 | .markdown-body dl { 430 | padding: 0; 431 | } 432 | 433 | .markdown-body dl dt { 434 | padding: 0; 435 | margin-top: 16px; 436 | font-size: 1em; 437 | font-style: italic; 438 | font-weight: bold; 439 | } 440 | 441 | .markdown-body dl dd { 442 | padding: 0 16px; 443 | margin-bottom: 16px; 444 | } 445 | 446 | .markdown-body blockquote { 447 | padding: 0 15px; 448 | color: #777; 449 | border-left: 4px solid #ddd; 450 | } 451 | 452 | .markdown-body blockquote>:first-child { 453 | margin-top: 0; 454 | } 455 | 456 | .markdown-body blockquote>:last-child { 457 | margin-bottom: 0; 458 | } 459 | 460 | .markdown-body table { 461 | display: block; 462 | width: 100%; 463 | overflow: auto; 464 | word-break: normal; 465 | word-break: keep-all; 466 | } 467 | 468 | .markdown-body table th { 469 | font-weight: bold; 470 | } 471 | 472 | .markdown-body table th, 473 | .markdown-body table td { 474 | padding: 6px 13px; 475 | border: 1px solid #ddd; 476 | } 477 | 478 | .markdown-body table tr { 479 | background-color: #fff; 480 | border-top: 1px solid #ccc; 481 | } 482 | 483 | .markdown-body table tr:nth-child(2n) { 484 | background-color: #f8f8f8; 485 | } 486 | 487 | .markdown-body img { 488 | max-width: 100%; 489 | -moz-box-sizing: border-box; 490 | box-sizing: border-box; 491 | } 492 | 493 | .markdown-body code, 494 | .markdown-body samp { 495 | padding: 0; 496 | padding-top: 0.2em; 497 | padding-bottom: 0.2em; 498 | margin: 0; 499 | font-size: 85%; 500 | background-color: rgba(0,0,0,0.04); 501 | border-radius: 3px; 502 | } 503 | 504 | .markdown-body code:before, 505 | .markdown-body code:after { 506 | letter-spacing: -0.2em; 507 | content: "\00a0"; 508 | } 509 | 510 | .markdown-body pre>code { 511 | padding: 0; 512 | margin: 0; 513 | font-size: 100%; 514 | word-break: normal; 515 | white-space: pre; 516 | background: transparent; 517 | border: 0; 518 | } 519 | 520 | .markdown-body .codehilite { 521 | margin-bottom: 16px; 522 | } 523 | 524 | .markdown-body .codehilite pre, 525 | .markdown-body pre { 526 | padding: 16px; 527 | overflow: auto; 528 | font-size: 85%; 529 | line-height: 1.45; 530 | background-color: #f7f7f7; 531 | border-radius: 3px; 532 | } 533 | 534 | .markdown-body .codehilite pre { 535 | margin-bottom: 0; 536 | word-break: normal; 537 | } 538 | 539 | .markdown-body pre { 540 | word-wrap: normal; 541 | } 542 | 543 | .markdown-body pre code { 544 | display: inline; 545 | max-width: initial; 546 | padding: 0; 547 | margin: 0; 548 | overflow: initial; 549 | line-height: inherit; 550 | word-wrap: normal; 551 | background-color: transparent; 552 | border: 0; 553 | } 554 | 555 | .markdown-body pre code:before, 556 | .markdown-body pre code:after { 557 | content: normal; 558 | } 559 | 560 | /* Admonition */ 561 | .markdown-body .admonition { 562 | -webkit-border-radius: 3px; 563 | -moz-border-radius: 3px; 564 | position: relative; 565 | border-radius: 3px; 566 | border: 1px solid #e0e0e0; 567 | border-left: 6px solid #333; 568 | padding: 10px 10px 10px 30px; 569 | } 570 | 571 | .markdown-body .admonition table { 572 | color: #333; 573 | } 574 | 575 | .markdown-body .admonition p { 576 | padding: 0; 577 | } 578 | 579 | .markdown-body .admonition-title { 580 | font-weight: bold; 581 | margin: 0; 582 | } 583 | 584 | .markdown-body .admonition>.admonition-title { 585 | color: #333; 586 | } 587 | 588 | .markdown-body .attention>.admonition-title { 589 | color: #a6d796; 590 | } 591 | 592 | .markdown-body .caution>.admonition-title { 593 | color: #d7a796; 594 | } 595 | 596 | .markdown-body .hint>.admonition-title { 597 | color: #96c6d7; 598 | } 599 | 600 | .markdown-body .danger>.admonition-title { 601 | color: #c25f77; 602 | } 603 | 604 | .markdown-body .question>.admonition-title { 605 | color: #96a6d7; 606 | } 607 | 608 | .markdown-body .note>.admonition-title { 609 | color: #d7c896; 610 | } 611 | 612 | .markdown-body .admonition:before, 613 | .markdown-body .attention:before, 614 | .markdown-body .caution:before, 615 | .markdown-body .hint:before, 616 | .markdown-body .danger:before, 617 | .markdown-body .question:before, 618 | .markdown-body .note:before { 619 | font: normal normal 16px fontawesome-mini; 620 | -moz-osx-font-smoothing: grayscale; 621 | -webkit-user-select: none; 622 | -moz-user-select: none; 623 | -ms-user-select: none; 624 | user-select: none; 625 | line-height: 1.5; 626 | color: #333; 627 | position: absolute; 628 | left: 0; 629 | top: 0; 630 | padding-top: 10px; 631 | padding-left: 10px; 632 | } 633 | 634 | .markdown-body .admonition:before { 635 | content: "\f056\00a0"; 636 | color: 333; 637 | } 638 | 639 | .markdown-body .attention:before { 640 | content: "\f058\00a0"; 641 | color: #a6d796; 642 | } 643 | 644 | .markdown-body .caution:before { 645 | content: "\f06a\00a0"; 646 | color: #d7a796; 647 | } 648 | 649 | .markdown-body .hint:before { 650 | content: "\f05a\00a0"; 651 | color: #96c6d7; 652 | } 653 | 654 | .markdown-body .danger:before { 655 | content: "\f057\00a0"; 656 | color: #c25f77; 657 | } 658 | 659 | .markdown-body .question:before { 660 | content: "\f059\00a0"; 661 | color: #96a6d7; 662 | } 663 | 664 | .markdown-body .note:before { 665 | content: "\f040\00a0"; 666 | color: #d7c896; 667 | } 668 | 669 | .markdown-body .admonition::after { 670 | content: normal; 671 | } 672 | 673 | .markdown-body .attention { 674 | border-left: 6px solid #a6d796; 675 | } 676 | 677 | .markdown-body .caution { 678 | border-left: 6px solid #d7a796; 679 | } 680 | 681 | .markdown-body .hint { 682 | border-left: 6px solid #96c6d7; 683 | } 684 | 685 | .markdown-body .danger { 686 | border-left: 6px solid #c25f77; 687 | } 688 | 689 | .markdown-body .question { 690 | border-left: 6px solid #96a6d7; 691 | } 692 | 693 | .markdown-body .note { 694 | border-left: 6px solid #d7c896; 695 | } 696 | 697 | .markdown-body .admonition>*:first-child { 698 | margin-top: 0 !important; 699 | } 700 | 701 | .markdown-body .admonition>*:last-child { 702 | margin-bottom: 0 !important; 703 | } 704 | 705 | /* progress bar*/ 706 | .markdown-body .progress { 707 | display: block; 708 | width: 300px; 709 | margin: 10px 0; 710 | height: 24px; 711 | -webkit-border-radius: 3px; 712 | -moz-border-radius: 3px; 713 | border-radius: 3px; 714 | background-color: #ededed; 715 | position: relative; 716 | box-shadow: inset -1px 1px 3px rgba(0, 0, 0, .1); 717 | } 718 | 719 | .markdown-body .progress-label { 720 | position: absolute; 721 | text-align: center; 722 | font-weight: bold; 723 | width: 100%; margin: 0; 724 | line-height: 24px; 725 | color: #333; 726 | text-shadow: 1px 1px 0 #fefefe, -1px -1px 0 #fefefe, -1px 1px 0 #fefefe, 1px -1px 0 #fefefe, 0 1px 0 #fefefe, 0 -1px 0 #fefefe, 1px 0 0 #fefefe, -1px 0 0 #fefefe, 1px 1px 2px #000; 727 | -webkit-font-smoothing: antialiased !important; 728 | white-space: nowrap; 729 | overflow: hidden; 730 | } 731 | 732 | .markdown-body .progress-bar { 733 | height: 24px; 734 | float: left; 735 | -webkit-border-radius: 3px; 736 | -moz-border-radius: 3px; 737 | border-radius: 3px; 738 | background-color: #96c6d7; 739 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(0, 0, 0, .1); 740 | background-size: 30px 30px; 741 | background-image: -webkit-linear-gradient( 742 | 135deg, rgba(255, 255, 255, .4) 27%, 743 | transparent 27%, 744 | transparent 52%, rgba(255, 255, 255, .4) 52%, 745 | rgba(255, 255, 255, .4) 77%, 746 | transparent 77%, transparent 747 | ); 748 | background-image: -moz-linear-gradient( 749 | 135deg, 750 | rgba(255, 255, 255, .4) 27%, transparent 27%, 751 | transparent 52%, rgba(255, 255, 255, .4) 52%, 752 | rgba(255, 255, 255, .4) 77%, transparent 77%, 753 | transparent 754 | ); 755 | background-image: -ms-linear-gradient( 756 | 135deg, 757 | rgba(255, 255, 255, .4) 27%, transparent 27%, 758 | transparent 52%, rgba(255, 255, 255, .4) 52%, 759 | rgba(255, 255, 255, .4) 77%, transparent 77%, 760 | transparent 761 | ); 762 | background-image: -o-linear-gradient( 763 | 135deg, 764 | rgba(255, 255, 255, .4) 27%, transparent 27%, 765 | transparent 52%, rgba(255, 255, 255, .4) 52%, 766 | rgba(255, 255, 255, .4) 77%, transparent 77%, 767 | transparent 768 | ); 769 | background-image: linear-gradient( 770 | 135deg, 771 | rgba(255, 255, 255, .4) 27%, transparent 27%, 772 | transparent 52%, rgba(255, 255, 255, .4) 52%, 773 | rgba(255, 255, 255, .4) 77%, transparent 77%, 774 | transparent 775 | ); 776 | } 777 | 778 | .markdown-body .progress-100plus .progress-bar { 779 | background-color: #a6d796; 780 | } 781 | 782 | .markdown-body .progress-80plus .progress-bar { 783 | background-color: #c6d796; 784 | } 785 | 786 | .markdown-body .progress-60plus .progress-bar { 787 | background-color: #d7c896; 788 | } 789 | 790 | .markdown-body .progress-40plus .progress-bar { 791 | background-color: #d7a796; 792 | } 793 | 794 | .markdown-body .progress-20plus .progress-bar { 795 | background-color: #d796a6; 796 | } 797 | 798 | .markdown-body .progress-0plus .progress-bar { 799 | background-color: #c25f77; 800 | } 801 | 802 | .markdown-body .candystripe-animate .progress-bar{ 803 | -webkit-animation: animate-stripes 3s linear infinite; 804 | -moz-animation: animate-stripes 3s linear infinite; 805 | animation: animate-stripes 3s linear infinite; 806 | } 807 | 808 | @-webkit-keyframes animate-stripes { 809 | 0% { 810 | background-position: 0 0; 811 | } 812 | 813 | 100% { 814 | background-position: 60px 0; 815 | } 816 | } 817 | 818 | @-moz-keyframes animate-stripes { 819 | 0% { 820 | background-position: 0 0; 821 | } 822 | 823 | 100% { 824 | background-position: 60px 0; 825 | } 826 | } 827 | 828 | @keyframes animate-stripes { 829 | 0% { 830 | background-position: 0 0; 831 | } 832 | 833 | 100% { 834 | background-position: 60px 0; 835 | } 836 | } 837 | 838 | .markdown-body .gloss .progress-bar { 839 | box-shadow: 840 | inset 0 4px 12px rgba(255, 255, 255, .7), 841 | inset 0 -12px 0 rgba(0, 0, 0, .05); 842 | } 843 | 844 | /* Multimarkdown Critic Blocks */ 845 | .markdown-body .critic_mark { 846 | background: #ff0; 847 | } 848 | 849 | .markdown-body .critic_delete { 850 | color: #c82829; 851 | text-decoration: line-through; 852 | } 853 | 854 | .markdown-body .critic_insert { 855 | color: #718c00 ; 856 | text-decoration: underline; 857 | } 858 | 859 | .markdown-body .critic_comment { 860 | color: #8e908c; 861 | font-style: italic; 862 | } 863 | 864 | .markdown-body .headeranchor { 865 | font: normal normal 16px fontawesome-mini; 866 | line-height: 1; 867 | display: inline-block; 868 | text-decoration: none; 869 | -webkit-font-smoothing: antialiased; 870 | -moz-osx-font-smoothing: grayscale; 871 | -webkit-user-select: none; 872 | -moz-user-select: none; 873 | -ms-user-select: none; 874 | user-select: none; 875 | } 876 | 877 | .headeranchor:before { 878 | content: '\e157'; 879 | } 880 | 881 | .markdown-body .task-list-item { 882 | list-style-type: none; 883 | } 884 | 885 | .markdown-body .task-list-item+.task-list-item { 886 | margin-top: 3px; 887 | } 888 | 889 | .markdown-body .task-list-item input { 890 | margin: 0 4px 0.25em -20px; 891 | vertical-align: middle; 892 | } 893 | 894 | /* Media */ 895 | @media only screen and (min-width: 480px) { 896 | .markdown-body { 897 | font-size:14px; 898 | } 899 | } 900 | 901 | @media only screen and (min-width: 768px) { 902 | .markdown-body { 903 | font-size:16px; 904 | } 905 | } 906 | 907 | @media print { 908 | .markdown-body * { 909 | background: transparent !important; 910 | color: black !important; 911 | filter:none !important; 912 | -ms-filter: none !important; 913 | } 914 | 915 | .markdown-body { 916 | font-size:12pt; 917 | max-width:100%; 918 | outline:none; 919 | border: 0; 920 | } 921 | 922 | .markdown-body a, 923 | .markdown-body a:visited { 924 | text-decoration: underline; 925 | } 926 | 927 | .markdown-body .headeranchor-link { 928 | display: none; 929 | } 930 | 931 | .markdown-body a[href]:after { 932 | content: " (" attr(href) ")"; 933 | } 934 | 935 | .markdown-body abbr[title]:after { 936 | content: " (" attr(title) ")"; 937 | } 938 | 939 | .markdown-body .ir a:after, 940 | .markdown-body a[href^="javascript:"]:after, 941 | .markdown-body a[href^="#"]:after { 942 | content: ""; 943 | } 944 | 945 | .markdown-body pre { 946 | white-space: pre; 947 | white-space: pre-wrap; 948 | word-wrap: break-word; 949 | } 950 | 951 | .markdown-body pre, 952 | .markdown-body blockquote { 953 | border: 1px solid #999; 954 | padding-right: 1em; 955 | page-break-inside: avoid; 956 | } 957 | 958 | .markdown-body .progress, 959 | .markdown-body .progress-bar { 960 | -moz-box-shadow: none; 961 | -webkit-box-shadow: none; 962 | box-shadow: none; 963 | } 964 | 965 | .markdown-body .progress { 966 | border: 1px solid #ddd; 967 | } 968 | 969 | .markdown-body .progress-bar { 970 | height: 22px; 971 | border-right: 1px solid #ddd; 972 | } 973 | 974 | .markdown-body tr, 975 | .markdown-body img { 976 | page-break-inside: avoid; 977 | } 978 | 979 | .markdown-body img { 980 | max-width: 100% !important; 981 | } 982 | 983 | .markdown-body p, 984 | .markdown-body h2, 985 | .markdown-body h3 { 986 | orphans: 3; 987 | widows: 3; 988 | } 989 | 990 | .markdown-body h2, 991 | .markdown-body h3 { 992 | page-break-after: avoid; 993 | } 994 | } 995 | -------------------------------------------------------------------------------- /css/pygments/github.css: -------------------------------------------------------------------------------- 1 | /*github*/ 2 | %(css_class)s {background-color:#fff;color:#333333;} 3 | %(css_class)s .hll {background-color:#ffffcc;} 4 | %(css_class)s .c{color:#999988;font-style:italic} 5 | %(css_class)s .err{color:#a61717;background-color:#e3d2d2} 6 | %(css_class)s .k{font-weight:bold} 7 | %(css_class)s .o{font-weight:bold} 8 | %(css_class)s .cm{color:#999988;font-style:italic} 9 | %(css_class)s .cp{color:#999999;font-weight:bold} 10 | %(css_class)s .c1{color:#999988;font-style:italic} 11 | %(css_class)s .cs{color:#999999;font-weight:bold;font-style:italic} 12 | %(css_class)s .gd{color:#000000;background-color:#ffdddd} 13 | %(css_class)s .ge{font-style:italic} 14 | %(css_class)s .gr{color:#aa0000} 15 | %(css_class)s .gh{color:#999999} 16 | %(css_class)s .gi{color:#000000;background-color:#ddffdd} 17 | %(css_class)s .go{color:#888888} 18 | %(css_class)s .gp{color:#555555} 19 | %(css_class)s .gs{font-weight:bold} 20 | %(css_class)s .gu{color:#800080;font-weight:bold} 21 | %(css_class)s .gt{color:#aa0000} 22 | %(css_class)s .kc{font-weight:bold} 23 | %(css_class)s .kd{font-weight:bold} 24 | %(css_class)s .kn{font-weight:bold} 25 | %(css_class)s .kp{font-weight:bold} 26 | %(css_class)s .kr{font-weight:bold} 27 | %(css_class)s .kt{color:#445588;font-weight:bold} 28 | %(css_class)s .m{color:#009999} 29 | %(css_class)s .s{color:#dd1144} 30 | %(css_class)s .n{color:#333333} 31 | %(css_class)s .na{color:teal} 32 | %(css_class)s .nb{color:#0086b3} 33 | %(css_class)s .nc{color:#445588;font-weight:bold} 34 | %(css_class)s .no{color:teal} 35 | %(css_class)s .ni{color:purple} 36 | %(css_class)s .ne{color:#990000;font-weight:bold} 37 | %(css_class)s .nf{color:#990000;font-weight:bold} 38 | %(css_class)s .nn{color:#555555} 39 | %(css_class)s .nt{color:navy} 40 | %(css_class)s .nv{color:teal} 41 | %(css_class)s .ow{font-weight:bold} 42 | %(css_class)s .w{color:#bbbbbb} 43 | %(css_class)s .mf{color:#009999} 44 | %(css_class)s .mh{color:#009999} 45 | %(css_class)s .mi{color:#009999} 46 | %(css_class)s .mo{color:#009999} 47 | %(css_class)s .sb{color:#dd1144} 48 | %(css_class)s .sc{color:#dd1144} 49 | %(css_class)s .sd{color:#dd1144} 50 | %(css_class)s .s2{color:#dd1144} 51 | %(css_class)s .se{color:#dd1144} 52 | %(css_class)s .sh{color:#dd1144} 53 | %(css_class)s .si{color:#dd1144} 54 | %(css_class)s .sx{color:#dd1144} 55 | %(css_class)s .sr{color:#009926} 56 | %(css_class)s .s1{color:#dd1144} 57 | %(css_class)s .ss{color:#990073} 58 | %(css_class)s .bp{color:#999999} 59 | %(css_class)s .vc{color:teal} 60 | %(css_class)s .vg{color:teal} 61 | %(css_class)s .vi{color:teal} 62 | %(css_class)s .il{color:#009999} 63 | %(css_class)s .gc{color:#999;background-color:#EAF2F5} 64 | -------------------------------------------------------------------------------- /css/pygments/github2014.css: -------------------------------------------------------------------------------- 1 | %(css_class)s {color:#333;background-color:#fff} 2 | %(css_class)s .hll {background-color: #f8eec7;} 3 | %(css_class)s .mf{color:#945277} 4 | %(css_class)s .mh{color:#945277} 5 | %(css_class)s .mi{color:#945277} 6 | %(css_class)s .mo{color:#945277} 7 | %(css_class)s .il{color:#945277} 8 | %(css_class)s .m{color:#945277} 9 | %(css_class)s .s{color:#df5000} 10 | %(css_class)s .sb{color:#df5000} 11 | %(css_class)s .sc{color:#df5000} 12 | %(css_class)s .sd{color:#df5000} 13 | %(css_class)s .s2{color:#df5000} 14 | %(css_class)s .se{color:#df5000} 15 | %(css_class)s .sh{color:#df5000} 16 | %(css_class)s .si{color:#df5000} 17 | %(css_class)s .sx{color:#df5000} 18 | %(css_class)s .s1{color:#df5000} 19 | %(css_class)s .kc{font-weight:bold} 20 | %(css_class)s .kd{font-weight:bold} 21 | %(css_class)s .kn{font-weight:bold} 22 | %(css_class)s .kp{font-weight:bold} 23 | %(css_class)s .kr{font-weight:bold} 24 | %(css_class)s .kt{font-weight:bold} 25 | %(css_class)s .k{font-weight:bold} 26 | %(css_class)s .o{font-weight:bold} 27 | %(css_class)s .kt{color:#458} 28 | %(css_class)s .c{color:#998;font-style:italic} 29 | %(css_class)s .cm{color:#998;font-style:italic} 30 | %(css_class)s .c1{color:#998;font-style:italic} 31 | %(css_class)s .cp{color:#999;font-weight:bold} 32 | %(css_class)s .cs{color:#999;font-weight:bold} 33 | %(css_class)s .cs{font-style:italic} 34 | %(css_class)s .n{color:#333} 35 | %(css_class)s .na{color:#008080} 36 | %(css_class)s .nv{color:#008080} 37 | %(css_class)s .vc{color:#008080} 38 | %(css_class)s .vg{color:#008080} 39 | %(css_class)s .vi{color:#008080} 40 | %(css_class)s .nb{color:#0086B3} 41 | %(css_class)s .nc{color:#458;font-weight:bold} 42 | %(css_class)s .no{color:#094e99} 43 | %(css_class)s .ni{color:#800080} 44 | %(css_class)s .ne{color:#990000;font-weight:bold} 45 | %(css_class)s .nf{color:#945277;font-weight:bold} 46 | %(css_class)s .nn{color:#555} 47 | %(css_class)s .nt{color:#000080} 48 | %(css_class)s .err{color:#a61717;background-color:#e3d2d2} 49 | %(css_class)s .gd{color:#000;background-color:#fdd} 50 | %(css_class)s .ge{font-style:italic} 51 | %(css_class)s .gr{color:#aa0000} 52 | %(css_class)s .gh{color:#999} 53 | %(css_class)s .gi{color:#000;background-color:#dfd} 54 | %(css_class)s .go{color:#888} 55 | %(css_class)s .gp{color:#555} 56 | %(css_class)s .gs{font-weight:bold} 57 | %(css_class)s .gu{color:#800080;font-weight:bold} 58 | %(css_class)s .gt{color:#aa0000} 59 | %(css_class)s .ow{font-weight:bold} 60 | %(css_class)s .w{color:#bbb} 61 | %(css_class)s .sr{color:#017936} 62 | %(css_class)s .ss{color:#8b467f} 63 | %(css_class)s .bp{color:#999} 64 | %(css_class)s .gc{color:#999;background-color:#EAF2F5} 65 | -------------------------------------------------------------------------------- /dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "*": { 3 | ">=3000": [ 4 | "pygments", 5 | "pyyaml", 6 | "python-markdown", 7 | "pymdownx" 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /desktop/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /desktop/README.md: -------------------------------------------------------------------------------- 1 | # python desktop 2 | 3 | This module has been extracted from Python core and benefits of some improvements. 4 | 5 | The goal of this module is simply to open documents with the default system viewer on various OS. 6 | 7 | The module is used in some of @revolunet SublimeText plugin, mainly to open web pages. 8 | 9 | 10 | ## Licence 11 | 12 | The original module license is "GNU Lesser General Public License" 13 | -------------------------------------------------------------------------------- /desktop/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Simple desktop integration for Python. This module provides desktop environment 5 | detection and resource opening support for a selection of common and 6 | standardised desktop environments. 7 | 8 | Copyright (C) 2005, 2006, 2007, 2008, 2009 Paul Boddie 9 | 10 | This program is free software; you can redistribute it and/or modify it under 11 | the terms of the GNU Lesser General Public License as published by the Free 12 | Software Foundation; either version 3 of the License, or (at your option) any 13 | later version. 14 | 15 | This program is distributed in the hope that it will be useful, but WITHOUT 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 18 | details. 19 | 20 | You should have received a copy of the GNU Lesser General Public License along 21 | with this program. If not, see . 22 | 23 | -------- 24 | 25 | Desktop Detection 26 | ----------------- 27 | 28 | To detect a specific desktop environment, use the get_desktop function. 29 | To detect whether the desktop environment is standardised (according to the 30 | proposed DESKTOP_LAUNCH standard), use the is_standard function. 31 | 32 | Opening URLs 33 | ------------ 34 | 35 | To open a URL in the current desktop environment, relying on the automatic 36 | detection of that environment, use the desktop.open function as follows: 37 | 38 | desktop.open("http://www.python.org") 39 | 40 | To override the detected desktop, specify the desktop parameter to the open 41 | function as follows: 42 | 43 | desktop.open("http://www.python.org", "KDE") # Insists on KDE 44 | desktop.open("http://www.python.org", "GNOME") # Insists on GNOME 45 | desktop.open("http://www.python.org", "MATE") # Insists on MATE 46 | 47 | Without overriding using the desktop parameter, the open function will attempt 48 | to use the "standard" desktop opening mechanism which is controlled by the 49 | DESKTOP_LAUNCH environment variable as described below. 50 | 51 | The DESKTOP_LAUNCH Environment Variable 52 | --------------------------------------- 53 | 54 | The DESKTOP_LAUNCH environment variable must be shell-quoted where appropriate, 55 | as shown in some of the following examples: 56 | 57 | DESKTOP_LAUNCH="kdialog --msgbox" Should present any opened URLs in 58 | their entirety in a KDE message box. 59 | (Command "kdialog" plus parameter.) 60 | DESKTOP_LAUNCH="my\ opener" Should run the "my opener" program to 61 | open URLs. 62 | (Command "my opener", no parameters.) 63 | DESKTOP_LAUNCH="my\ opener --url" Should run the "my opener" program to 64 | open URLs. 65 | (Command "my opener" plus parameter.) 66 | 67 | Details of the DESKTOP_LAUNCH environment variable convention can be found here: 68 | http://lists.freedesktop.org/archives/xdg/2004-August/004489.html 69 | 70 | Other Modules 71 | ------------- 72 | 73 | The desktop.dialog module provides support for opening dialogue boxes. 74 | The desktop.windows module permits the inspection of desktop windows. 75 | """ 76 | 77 | __version__ = "0.4" 78 | 79 | import os 80 | import sys 81 | 82 | # Provide suitable process creation functions. 83 | 84 | try: 85 | import subprocess 86 | def _run(cmd, shell, wait): 87 | opener = subprocess.Popen(cmd, shell=shell) 88 | if wait: opener.wait() 89 | return opener.pid 90 | 91 | def _readfrom(cmd, shell): 92 | opener = subprocess.Popen(cmd, shell=shell, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 93 | opener.stdin.close() 94 | return opener.stdout.read() 95 | 96 | def _status(cmd, shell): 97 | opener = subprocess.Popen(cmd, shell=shell) 98 | opener.wait() 99 | return opener.returncode == 0 100 | 101 | except ImportError: 102 | import popen2 103 | def _run(cmd, shell, wait): 104 | opener = popen2.Popen3(cmd) 105 | if wait: opener.wait() 106 | return opener.pid 107 | 108 | def _readfrom(cmd, shell): 109 | opener = popen2.Popen3(cmd) 110 | opener.tochild.close() 111 | opener.childerr.close() 112 | return opener.fromchild.read() 113 | 114 | def _status(cmd, shell): 115 | opener = popen2.Popen3(cmd) 116 | opener.wait() 117 | return opener.poll() == 0 118 | 119 | import subprocess 120 | 121 | # Private functions. 122 | 123 | def _get_x11_vars(): 124 | 125 | "Return suitable environment definitions for X11." 126 | 127 | if not os.environ.get("DISPLAY", "").strip(): 128 | return "DISPLAY=:0.0 " 129 | else: 130 | return "" 131 | 132 | def _is_xfce(): 133 | 134 | "Return whether XFCE is in use." 135 | 136 | # XFCE detection involves testing the output of a program. 137 | 138 | try: 139 | return _readfrom(_get_x11_vars() + "xprop -root _DT_SAVE_MODE", shell=1).decode("utf-8").strip().endswith(' = "xfce4"') 140 | except OSError: 141 | return 0 142 | 143 | def _is_x11(): 144 | 145 | "Return whether the X Window System is in use." 146 | 147 | return "DISPLAY" in os.environ 148 | 149 | # Introspection functions. 150 | 151 | def get_desktop(): 152 | 153 | """ 154 | Detect the current desktop environment, returning the name of the 155 | environment. If no environment could be detected, None is returned. 156 | """ 157 | 158 | if "KDE_FULL_SESSION" in os.environ or \ 159 | "KDE_MULTIHEAD" in os.environ: 160 | return "KDE" 161 | elif "GNOME_DESKTOP_SESSION_ID" in os.environ or \ 162 | "GNOME_KEYRING_SOCKET" in os.environ: 163 | return "GNOME" 164 | elif "MATE_DESKTOP_SESSION_ID" in os.environ or \ 165 | "MATE_KEYRING_SOCKET" in os.environ: 166 | return "MATE" 167 | elif sys.platform == "darwin": 168 | return "Mac OS X" 169 | elif hasattr(os, "startfile"): 170 | return "Windows" 171 | elif _is_xfce(): 172 | return "XFCE" 173 | 174 | # KDE, GNOME, MATE and XFCE run on X11, so we have to test for X11 last. 175 | 176 | if _is_x11(): 177 | return "X11" 178 | else: 179 | return None 180 | 181 | def use_desktop(desktop): 182 | 183 | """ 184 | Decide which desktop should be used, based on the detected desktop and a 185 | supplied 'desktop' argument (which may be None). Return an identifier 186 | indicating the desktop type as being either "standard" or one of the results 187 | from the 'get_desktop' function. 188 | """ 189 | 190 | # Attempt to detect a desktop environment. 191 | 192 | detected = get_desktop() 193 | 194 | # Start with desktops whose existence can be easily tested. 195 | 196 | if (desktop is None or desktop == "standard") and is_standard(): 197 | return "standard" 198 | elif (desktop is None or desktop == "Windows") and detected == "Windows": 199 | return "Windows" 200 | 201 | # Test for desktops where the overriding is not verified. 202 | 203 | elif (desktop or detected) == "KDE": 204 | return "KDE" 205 | elif (desktop or detected) == "GNOME": 206 | return "GNOME" 207 | elif (desktop or detected) == "MATE": 208 | return "MATE" 209 | elif (desktop or detected) == "XFCE": 210 | return "XFCE" 211 | elif (desktop or detected) == "Mac OS X": 212 | return "Mac OS X" 213 | elif (desktop or detected) == "X11": 214 | return "X11" 215 | else: 216 | return None 217 | 218 | def is_standard(): 219 | 220 | """ 221 | Return whether the current desktop supports standardised application 222 | launching. 223 | """ 224 | 225 | return "DESKTOP_LAUNCH" in os.environ 226 | 227 | # Activity functions. 228 | 229 | def open(url, desktop=None, wait=0): 230 | 231 | """ 232 | Open the 'url' in the current desktop's preferred file browser. If the 233 | optional 'desktop' parameter is specified then attempt to use that 234 | particular desktop environment's mechanisms to open the 'url' instead of 235 | guessing or detecting which environment is being used. 236 | 237 | Suggested values for 'desktop' are "standard", "KDE", "GNOME", "GNOME", 238 | "XFCE", "Mac OS X", "Windows" where "standard" employs a DESKTOP_LAUNCH 239 | environment variable to open the specified 'url'. DESKTOP_LAUNCH should 240 | be a command, possibly followed by arguments, and must have any special 241 | characters shell-escaped. 242 | 243 | The process identifier of the "opener" (ie. viewer, editor, browser or 244 | program) associated with the 'url' is returned by this function. If the 245 | process identifier cannot be determined, None is returned. 246 | 247 | An optional 'wait' parameter is also available for advanced usage and, if 248 | 'wait' is set to a true value, this function will wait for the launching 249 | mechanism to complete before returning (as opposed to immediately returning 250 | as is the default behaviour). 251 | """ 252 | 253 | # Decide on the desktop environment in use. 254 | 255 | desktop_in_use = use_desktop(desktop) 256 | 257 | if desktop_in_use == "standard": 258 | arg = "".join([os.environ["DESKTOP_LAUNCH"], subprocess.mkarg(url)]) 259 | return _run(arg, 1, wait) 260 | 261 | elif desktop_in_use == "Windows": 262 | # NOTE: This returns None in current implementations. 263 | return os.startfile(url) 264 | 265 | elif desktop_in_use == "KDE": 266 | cmd = ["xdg-open", url] 267 | 268 | elif desktop_in_use == "GNOME": 269 | cmd = ["xdg-open", url] 270 | 271 | elif desktop_in_use == "MATE": 272 | cmd = ["xdg-open", url] 273 | 274 | elif desktop_in_use == "XFCE": 275 | cmd = ["xdg-open", url] 276 | 277 | elif desktop_in_use == "Mac OS X": 278 | cmd = ["open", url] 279 | 280 | elif desktop_in_use == "X11" and "BROWSER" in os.environ: 281 | cmd = [os.environ["BROWSER"], url] 282 | 283 | elif desktop_in_use == "X11": 284 | cmd = ["xdg-open", url] 285 | 286 | # Finish with an error where no suitable desktop was identified. 287 | 288 | else: 289 | raise OSError("Desktop '%s' not supported (neither DESKTOP_LAUNCH nor os.startfile could be used)" % desktop_in_use) 290 | 291 | return _run(cmd, 0, wait) 292 | 293 | # vim: tabstop=4 expandtab shiftwidth=4 294 | -------------------------------------------------------------------------------- /desktop/dialog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Simple desktop dialogue box support for Python. 5 | 6 | Copyright (C) 2007, 2009 Paul Boddie 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT 14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 16 | details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License along 19 | with this program. If not, see . 20 | 21 | -------- 22 | 23 | Opening Dialogue Boxes (Dialogs) 24 | -------------------------------- 25 | 26 | To open a dialogue box (dialog) in the current desktop environment, relying on 27 | the automatic detection of that environment, use the appropriate dialogue box 28 | class: 29 | 30 | question = desktop.dialog.Question("Are you sure?") 31 | result = question.open() 32 | 33 | To override the detected desktop, specify the desktop parameter to the open 34 | function as follows: 35 | 36 | question.open("KDE") # Insists on KDE 37 | question.open("GNOME") # Insists on GNOME 38 | question.open("MATE") # Insists on MATE 39 | 40 | The dialogue box options are documented in each class's docstring. 41 | 42 | Available dialogue box classes are listed in the desktop.dialog.available 43 | attribute. 44 | 45 | Supported desktop environments are listed in the desktop.dialog.supported 46 | attribute. 47 | """ 48 | 49 | from desktop import use_desktop, _run, _readfrom, _status 50 | 51 | class _wrapper: 52 | def __init__(self, handler): 53 | self.handler = handler 54 | 55 | class _readvalue(_wrapper): 56 | def __call__(self, cmd, shell): 57 | return self.handler(cmd, shell).strip() 58 | 59 | class _readinput(_wrapper): 60 | def __call__(self, cmd, shell): 61 | return self.handler(cmd, shell)[:-1] 62 | 63 | class _readvalues_kdialog(_wrapper): 64 | def __call__(self, cmd, shell): 65 | result = self.handler(cmd, shell).strip().strip('"') 66 | if result: 67 | return result.split('" "') 68 | else: 69 | return [] 70 | 71 | class _readvalues_zenity(_wrapper): 72 | def __call__(self, cmd, shell): 73 | result = self.handler(cmd, shell).strip() 74 | if result: 75 | return result.split("|") 76 | else: 77 | return [] 78 | 79 | class _readvalues_Xdialog(_wrapper): 80 | def __call__(self, cmd, shell): 81 | result = self.handler(cmd, shell).strip() 82 | if result: 83 | return result.split("/") 84 | else: 85 | return [] 86 | 87 | # Dialogue parameter classes. 88 | 89 | class String: 90 | 91 | "A generic parameter." 92 | 93 | def __init__(self, name): 94 | self.name = name 95 | 96 | def convert(self, value, program): 97 | return [value or ""] 98 | 99 | class Strings(String): 100 | 101 | "Multiple string parameters." 102 | 103 | def convert(self, value, program): 104 | return value or [] 105 | 106 | class StringPairs(String): 107 | 108 | "Multiple string parameters duplicated to make identifiers." 109 | 110 | def convert(self, value, program): 111 | l = [] 112 | for v in value: 113 | l.append(v) 114 | l.append(v) 115 | return l 116 | 117 | class StringKeyword: 118 | 119 | "A keyword parameter." 120 | 121 | def __init__(self, keyword, name): 122 | self.keyword = keyword 123 | self.name = name 124 | 125 | def convert(self, value, program): 126 | return [self.keyword + "=" + (value or "")] 127 | 128 | class StringKeywords: 129 | 130 | "Multiple keyword parameters." 131 | 132 | def __init__(self, keyword, name): 133 | self.keyword = keyword 134 | self.name = name 135 | 136 | def convert(self, value, program): 137 | l = [] 138 | for v in value or []: 139 | l.append(self.keyword + "=" + v) 140 | return l 141 | 142 | class Integer(String): 143 | 144 | "An integer parameter." 145 | 146 | defaults = { 147 | "width" : 40, 148 | "height" : 15, 149 | "list_height" : 10 150 | } 151 | scale = 8 152 | 153 | def __init__(self, name, pixels=0): 154 | String.__init__(self, name) 155 | if pixels: 156 | self.factor = self.scale 157 | else: 158 | self.factor = 1 159 | 160 | def convert(self, value, program): 161 | if value is None: 162 | value = self.defaults[self.name] 163 | return [str(int(value) * self.factor)] 164 | 165 | class IntegerKeyword(Integer): 166 | 167 | "An integer keyword parameter." 168 | 169 | def __init__(self, keyword, name, pixels=0): 170 | Integer.__init__(self, name, pixels) 171 | self.keyword = keyword 172 | 173 | def convert(self, value, program): 174 | if value is None: 175 | value = self.defaults[self.name] 176 | return [self.keyword + "=" + str(int(value) * self.factor)] 177 | 178 | class Boolean(String): 179 | 180 | "A boolean parameter." 181 | 182 | values = { 183 | "kdialog" : ["off", "on"], 184 | "zenity" : ["FALSE", "TRUE"], 185 | "Xdialog" : ["off", "on"] 186 | } 187 | 188 | def convert(self, value, program): 189 | values = self.values[program] 190 | if value: 191 | return [values[1]] 192 | else: 193 | return [values[0]] 194 | 195 | class MenuItemList(String): 196 | 197 | "A menu item list parameter." 198 | 199 | def convert(self, value, program): 200 | l = [] 201 | for v in value: 202 | l.append(v.value) 203 | l.append(v.text) 204 | return l 205 | 206 | class ListItemList(String): 207 | 208 | "A radiolist/checklist item list parameter." 209 | 210 | def __init__(self, name, status_first=0): 211 | String.__init__(self, name) 212 | self.status_first = status_first 213 | 214 | def convert(self, value, program): 215 | l = [] 216 | for v in value: 217 | boolean = Boolean(None) 218 | status = boolean.convert(v.status, program) 219 | if self.status_first: 220 | l += status 221 | l.append(v.value) 222 | l.append(v.text) 223 | if not self.status_first: 224 | l += status 225 | return l 226 | 227 | # Dialogue argument values. 228 | 229 | class MenuItem: 230 | 231 | "A menu item which can also be used with radiolists and checklists." 232 | 233 | def __init__(self, value, text, status=0): 234 | self.value = value 235 | self.text = text 236 | self.status = status 237 | 238 | # Dialogue classes. 239 | 240 | class Dialogue: 241 | 242 | commands = { 243 | "KDE" : "kdialog", 244 | "GNOME" : "zenity", 245 | "MATE" : "zenity", 246 | "XFCE" : "zenity", # NOTE: Based on observations with Xubuntu. 247 | "X11" : "Xdialog" 248 | } 249 | 250 | def open(self, desktop=None): 251 | 252 | """ 253 | Open a dialogue box (dialog) using a program appropriate to the desktop 254 | environment in use. 255 | 256 | If the optional 'desktop' parameter is specified then attempt to use 257 | that particular desktop environment's mechanisms to open the dialog 258 | instead of guessing or detecting which environment is being used. 259 | 260 | Suggested values for 'desktop' are "standard", "KDE", "GNOME", 261 | "MATE", "Mac OS X", "Windows". 262 | 263 | The result of the dialogue interaction may be a string indicating user 264 | input (for Input, Password, Menu, Pulldown), a list of strings 265 | indicating selections of one or more items (for RadioList, CheckList), 266 | or a value indicating true or false (for Question, Warning, Message, 267 | Error). 268 | 269 | Where a string value may be expected but no choice is made, an empty 270 | string may be returned. Similarly, where a list of values is expected 271 | but no choice is made, an empty list may be returned. 272 | """ 273 | 274 | # Decide on the desktop environment in use. 275 | 276 | desktop_in_use = use_desktop(desktop) 277 | 278 | # Get the program. 279 | 280 | try: 281 | program = self.commands[desktop_in_use] 282 | except KeyError: 283 | raise OSError("Desktop '%s' not supported (no known dialogue box command could be suggested)" % desktop_in_use) 284 | 285 | # The handler is one of the functions communicating with the subprocess. 286 | # Some handlers return boolean values, others strings. 287 | 288 | handler, options = self.info[program] 289 | 290 | cmd = [program] 291 | for option in options: 292 | if isinstance(option, str): 293 | cmd.append(option) 294 | else: 295 | value = getattr(self, option.name, None) 296 | cmd += option.convert(value, program) 297 | 298 | return handler(cmd, 0) 299 | 300 | class Simple(Dialogue): 301 | def __init__(self, text, width=None, height=None): 302 | self.text = text 303 | self.width = width 304 | self.height = height 305 | 306 | class Question(Simple): 307 | 308 | """ 309 | A dialogue asking a question and showing response buttons. 310 | Options: text, width (in characters), height (in characters) 311 | Response: a boolean value indicating an affirmative response (true) or a 312 | negative response 313 | """ 314 | 315 | name = "question" 316 | info = { 317 | "kdialog" : (_status, ["--yesno", String("text")]), 318 | "zenity" : (_status, ["--question", StringKeyword("--text", "text")]), 319 | "Xdialog" : (_status, ["--stdout", "--yesno", String("text"), Integer("height"), Integer("width")]), 320 | } 321 | 322 | class Warning(Simple): 323 | 324 | """ 325 | A dialogue asking a question and showing response buttons. 326 | Options: text, width (in characters), height (in characters) 327 | Response: a boolean value indicating an affirmative response (true) or a 328 | negative response 329 | """ 330 | 331 | name = "warning" 332 | info = { 333 | "kdialog" : (_status, ["--warningyesno", String("text")]), 334 | "zenity" : (_status, ["--warning", StringKeyword("--text", "text")]), 335 | "Xdialog" : (_status, ["--stdout", "--yesno", String("text"), Integer("height"), Integer("width")]), 336 | } 337 | 338 | class Message(Simple): 339 | 340 | """ 341 | A message dialogue. 342 | Options: text, width (in characters), height (in characters) 343 | Response: a boolean value indicating an affirmative response (true) or a 344 | negative response 345 | """ 346 | 347 | name = "message" 348 | info = { 349 | "kdialog" : (_status, ["--msgbox", String("text")]), 350 | "zenity" : (_status, ["--info", StringKeyword("--text", "text")]), 351 | "Xdialog" : (_status, ["--stdout", "--msgbox", String("text"), Integer("height"), Integer("width")]), 352 | } 353 | 354 | class Error(Simple): 355 | 356 | """ 357 | An error dialogue. 358 | Options: text, width (in characters), height (in characters) 359 | Response: a boolean value indicating an affirmative response (true) or a 360 | negative response 361 | """ 362 | 363 | name = "error" 364 | info = { 365 | "kdialog" : (_status, ["--error", String("text")]), 366 | "zenity" : (_status, ["--error", StringKeyword("--text", "text")]), 367 | "Xdialog" : (_status, ["--stdout", "--msgbox", String("text"), Integer("height"), Integer("width")]), 368 | } 369 | 370 | class Menu(Simple): 371 | 372 | """ 373 | A menu of options, one of which being selectable. 374 | Options: text, width (in characters), height (in characters), 375 | list_height (in items), items (MenuItem objects) 376 | Response: a value corresponding to the chosen item 377 | """ 378 | 379 | name = "menu" 380 | info = { 381 | "kdialog" : (_readvalue(_readfrom), ["--menu", String("text"), MenuItemList("items")]), 382 | "zenity" : (_readvalue(_readfrom), ["--list", StringKeyword("--text", "text"), StringKeywords("--column", "titles"), 383 | MenuItemList("items")] 384 | ), 385 | "Xdialog" : (_readvalue(_readfrom), ["--stdout", "--menubox", 386 | String("text"), Integer("height"), Integer("width"), Integer("list_height"), MenuItemList("items")] 387 | ), 388 | } 389 | item = MenuItem 390 | number_of_titles = 2 391 | 392 | def __init__(self, text, titles, items=None, width=None, height=None, list_height=None): 393 | 394 | """ 395 | Initialise a menu with the given heading 'text', column 'titles', and 396 | optional 'items' (which may be added later), 'width' (in characters), 397 | 'height' (in characters) and 'list_height' (in items). 398 | """ 399 | 400 | Simple.__init__(self, text, width, height) 401 | self.titles = ([""] * self.number_of_titles + titles)[-self.number_of_titles:] 402 | self.items = items or [] 403 | self.list_height = list_height 404 | 405 | def add(self, *args, **kw): 406 | 407 | """ 408 | Add an item, passing the given arguments to the appropriate item class. 409 | """ 410 | 411 | self.items.append(self.item(*args, **kw)) 412 | 413 | class RadioList(Menu): 414 | 415 | """ 416 | A list of radio buttons, one of which being selectable. 417 | Options: text, width (in characters), height (in characters), 418 | list_height (in items), items (MenuItem objects), titles 419 | Response: a list of values corresponding to chosen items (since some 420 | programs, eg. zenity, appear to support multiple default 421 | selections) 422 | """ 423 | 424 | name = "radiolist" 425 | info = { 426 | "kdialog" : (_readvalues_kdialog(_readfrom), ["--radiolist", String("text"), ListItemList("items")]), 427 | "zenity" : (_readvalues_zenity(_readfrom), 428 | ["--list", "--radiolist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"), 429 | ListItemList("items", 1)] 430 | ), 431 | "Xdialog" : (_readvalues_Xdialog(_readfrom), ["--stdout", "--radiolist", 432 | String("text"), Integer("height"), Integer("width"), Integer("list_height"), ListItemList("items")] 433 | ), 434 | } 435 | number_of_titles = 3 436 | 437 | class CheckList(Menu): 438 | 439 | """ 440 | A list of checkboxes, many being selectable. 441 | Options: text, width (in characters), height (in characters), 442 | list_height (in items), items (MenuItem objects), titles 443 | Response: a list of values corresponding to chosen items 444 | """ 445 | 446 | name = "checklist" 447 | info = { 448 | "kdialog" : (_readvalues_kdialog(_readfrom), ["--checklist", String("text"), ListItemList("items")]), 449 | "zenity" : (_readvalues_zenity(_readfrom), 450 | ["--list", "--checklist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"), 451 | ListItemList("items", 1)] 452 | ), 453 | "Xdialog" : (_readvalues_Xdialog(_readfrom), ["--stdout", "--checklist", 454 | String("text"), Integer("height"), Integer("width"), Integer("list_height"), ListItemList("items")] 455 | ), 456 | } 457 | number_of_titles = 3 458 | 459 | class Pulldown(Menu): 460 | 461 | """ 462 | A pull-down menu of options, one of which being selectable. 463 | Options: text, width (in characters), height (in characters), 464 | items (list of values) 465 | Response: a value corresponding to the chosen item 466 | """ 467 | 468 | name = "pulldown" 469 | info = { 470 | "kdialog" : (_readvalue(_readfrom), ["--combobox", String("text"), Strings("items")]), 471 | "zenity" : (_readvalue(_readfrom), 472 | ["--list", "--radiolist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"), 473 | StringPairs("items")] 474 | ), 475 | "Xdialog" : (_readvalue(_readfrom), 476 | ["--stdout", "--combobox", String("text"), Integer("height"), Integer("width"), Strings("items")]), 477 | } 478 | item = str 479 | number_of_titles = 2 480 | 481 | class Input(Simple): 482 | 483 | """ 484 | An input dialogue, consisting of an input field. 485 | Options: text, input, width (in characters), height (in characters) 486 | Response: the text entered into the dialogue by the user 487 | """ 488 | 489 | name = "input" 490 | info = { 491 | "kdialog" : (_readinput(_readfrom), 492 | ["--inputbox", String("text"), String("data")]), 493 | "zenity" : (_readinput(_readfrom), 494 | ["--entry", StringKeyword("--text", "text"), StringKeyword("--entry-text", "data")]), 495 | "Xdialog" : (_readinput(_readfrom), 496 | ["--stdout", "--inputbox", String("text"), Integer("height"), Integer("width"), String("data")]), 497 | } 498 | 499 | def __init__(self, text, data="", width=None, height=None): 500 | Simple.__init__(self, text, width, height) 501 | self.data = data 502 | 503 | class Password(Input): 504 | 505 | """ 506 | A password dialogue, consisting of a password entry field. 507 | Options: text, width (in characters), height (in characters) 508 | Response: the text entered into the dialogue by the user 509 | """ 510 | 511 | name = "password" 512 | info = { 513 | "kdialog" : (_readinput(_readfrom), 514 | ["--password", String("text")]), 515 | "zenity" : (_readinput(_readfrom), 516 | ["--entry", StringKeyword("--text", "text"), "--hide-text"]), 517 | "Xdialog" : (_readinput(_readfrom), 518 | ["--stdout", "--password", "--inputbox", String("text"), Integer("height"), Integer("width")]), 519 | } 520 | 521 | class TextFile(Simple): 522 | 523 | """ 524 | A text file input box. 525 | Options: filename, text, width (in characters), height (in characters) 526 | Response: any text returned by the dialogue program (typically an empty 527 | string) 528 | """ 529 | 530 | name = "textfile" 531 | info = { 532 | "kdialog" : (_readfrom, ["--textbox", String("filename"), Integer("width", pixels=1), Integer("height", pixels=1)]), 533 | "zenity" : (_readfrom, ["--text-info", StringKeyword("--filename", "filename"), IntegerKeyword("--width", "width", pixels=1), 534 | IntegerKeyword("--height", "height", pixels=1)] 535 | ), 536 | "Xdialog" : (_readfrom, ["--stdout", "--textbox", String("filename"), Integer("height"), Integer("width")]), 537 | } 538 | 539 | def __init__(self, filename, text="", width=None, height=None): 540 | Simple.__init__(self, text, width, height) 541 | self.filename = filename 542 | 543 | # Available dialogues. 544 | 545 | available = [Question, Warning, Message, Error, Menu, CheckList, RadioList, Input, Password, Pulldown, TextFile] 546 | 547 | # Supported desktop environments. 548 | 549 | supported = list(Dialogue.commands.keys()) 550 | 551 | # vim: tabstop=4 expandtab shiftwidth=4 552 | -------------------------------------------------------------------------------- /desktop/windows.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Simple desktop window enumeration for Python. 5 | 6 | Copyright (C) 2007, 2008, 2009 Paul Boddie 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT 14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 16 | details. 17 | 18 | You should have received a copy of the GNU Lesser General Public License along 19 | with this program. If not, see . 20 | 21 | -------- 22 | 23 | Finding Open Windows on the Desktop 24 | ----------------------------------- 25 | 26 | To obtain a list of windows, use the desktop.windows.list function as follows: 27 | 28 | windows = desktop.windows.list() 29 | 30 | To obtain the root window, typically the desktop background, use the 31 | desktop.windows.root function as follows: 32 | 33 | root = desktop.windows.root() 34 | 35 | Each window object can be inspected through a number of methods. For example: 36 | 37 | name = window.name() 38 | width, height = window.size() 39 | x, y = window.position() 40 | child_windows = window.children() 41 | 42 | See the desktop.windows.Window class for more information. 43 | """ 44 | 45 | from desktop import _is_x11, _get_x11_vars, _readfrom, use_desktop 46 | import re 47 | 48 | # System functions. 49 | 50 | def _xwininfo(identifier, action): 51 | if identifier is None: 52 | args = "-root" 53 | else: 54 | args = "-id " + identifier 55 | 56 | s = _readfrom(_get_x11_vars() + "xwininfo %s -%s" % (args, action), shell=1) 57 | 58 | # Return a mapping of keys to values for the "stats" action. 59 | 60 | if action == "stats": 61 | d = {} 62 | for line in s.split("\n"): 63 | fields = line.split(":") 64 | if len(fields) < 2: 65 | continue 66 | key, value = fields[0].strip(), ":".join(fields[1:]).strip() 67 | d[key] = value 68 | 69 | return d 70 | 71 | # Otherwise, return the raw output. 72 | 73 | else: 74 | return s 75 | 76 | def _get_int_properties(d, properties): 77 | results = [] 78 | for property in properties: 79 | results.append(int(d[property])) 80 | return results 81 | 82 | # Finder functions. 83 | 84 | def find_all(name): 85 | return 1 86 | 87 | def find_named(name): 88 | return name is not None 89 | 90 | def find_by_name(name): 91 | return lambda n, t=name: n == t 92 | 93 | # Window classes. 94 | # NOTE: X11 is the only supported desktop so far. 95 | 96 | class Window: 97 | 98 | "A window on the desktop." 99 | 100 | _name_pattern = re.compile(r':\s+\(.*?\)\s+[-0-9x+]+\s+[-0-9+]+$') 101 | _absent_names = "(has no name)", "(the root window) (has no name)" 102 | 103 | def __init__(self, identifier): 104 | 105 | "Initialise the window with the given 'identifier'." 106 | 107 | self.identifier = identifier 108 | 109 | # Finder methods (from above). 110 | 111 | self.find_all = find_all 112 | self.find_named = find_named 113 | self.find_by_name = find_by_name 114 | 115 | def __repr__(self): 116 | return "Window(%r)" % self.identifier 117 | 118 | # Methods which deal with the underlying commands. 119 | 120 | def _get_handle_and_name(self, text): 121 | fields = text.strip().split(" ") 122 | handle = fields[0] 123 | 124 | # Get the "" part, stripping off the quotes. 125 | 126 | name = " ".join(fields[1:]) 127 | if len(name) > 1 and name[0] == '"' and name[-1] == '"': 128 | name = name[1:-1] 129 | 130 | if name in self._absent_names: 131 | return handle, None 132 | else: 133 | return handle, name 134 | 135 | def _get_this_handle_and_name(self, line): 136 | fields = line.split(":") 137 | return self._get_handle_and_name(":".join(fields[1:])) 138 | 139 | def _get_descendant_handle_and_name(self, line): 140 | match = self._name_pattern.search(line) 141 | if match: 142 | return self._get_handle_and_name(line[:match.start()].strip()) 143 | else: 144 | raise OSError("Window information from %r did not contain window details." % line) 145 | 146 | def _descendants(self, s, fn): 147 | handles = [] 148 | adding = 0 149 | for line in s.split("\n"): 150 | if line.endswith("child:") or line.endswith("children:"): 151 | if not adding: 152 | adding = 1 153 | elif adding and line: 154 | handle, name = self._get_descendant_handle_and_name(line) 155 | if fn(name): 156 | handles.append(handle) 157 | return [Window(handle) for handle in handles] 158 | 159 | # Public methods. 160 | 161 | def children(self, all=0): 162 | 163 | """ 164 | Return a list of windows which are children of this window. If the 165 | optional 'all' parameter is set to a true value, all such windows will 166 | be returned regardless of whether they have any name information. 167 | """ 168 | 169 | s = _xwininfo(self.identifier, "children") 170 | return self._descendants(s, all and self.find_all or self.find_named) 171 | 172 | def descendants(self, all=0): 173 | 174 | """ 175 | Return a list of windows which are descendants of this window. If the 176 | optional 'all' parameter is set to a true value, all such windows will 177 | be returned regardless of whether they have any name information. 178 | """ 179 | 180 | s = _xwininfo(self.identifier, "tree") 181 | return self._descendants(s, all and self.find_all or self.find_named) 182 | 183 | def find(self, callable): 184 | 185 | """ 186 | Return windows using the given 'callable' (returning a true or a false 187 | value when invoked with a window name) for descendants of this window. 188 | """ 189 | 190 | s = _xwininfo(self.identifier, "tree") 191 | return self._descendants(s, callable) 192 | 193 | def name(self): 194 | 195 | "Return the name of the window." 196 | 197 | d = _xwininfo(self.identifier, "stats") 198 | 199 | # Format is 'xwininfo: Window id: "" 200 | 201 | return self._get_this_handle_and_name(d["xwininfo"])[1] 202 | 203 | def size(self): 204 | 205 | "Return a tuple containing the width and height of this window." 206 | 207 | d = _xwininfo(self.identifier, "stats") 208 | return _get_int_properties(d, ["Width", "Height"]) 209 | 210 | def position(self): 211 | 212 | "Return a tuple containing the upper left co-ordinates of this window." 213 | 214 | d = _xwininfo(self.identifier, "stats") 215 | return _get_int_properties(d, ["Absolute upper-left X", "Absolute upper-left Y"]) 216 | 217 | def displayed(self): 218 | 219 | """ 220 | Return whether the window is displayed in some way (but not necessarily 221 | visible on the current screen). 222 | """ 223 | 224 | d = _xwininfo(self.identifier, "stats") 225 | return d["Map State"] != "IsUnviewable" 226 | 227 | def visible(self): 228 | 229 | "Return whether the window is displayed and visible." 230 | 231 | d = _xwininfo(self.identifier, "stats") 232 | return d["Map State"] == "IsViewable" 233 | 234 | def list(desktop=None): 235 | 236 | """ 237 | Return a list of windows for the current desktop. If the optional 'desktop' 238 | parameter is specified then attempt to use that particular desktop 239 | environment's mechanisms to look for windows. 240 | """ 241 | 242 | root_window = root(desktop) 243 | window_list = [window for window in root_window.descendants() if window.displayed()] 244 | window_list.insert(0, root_window) 245 | return window_list 246 | 247 | def root(desktop=None): 248 | 249 | """ 250 | Return the root window for the current desktop. If the optional 'desktop' 251 | parameter is specified then attempt to use that particular desktop 252 | environment's mechanisms to look for windows. 253 | """ 254 | 255 | # NOTE: The desktop parameter is currently ignored and X11 is tested for 256 | # NOTE: directly. 257 | 258 | if _is_x11(): 259 | return Window(None) 260 | else: 261 | raise OSError("Desktop '%s' not supported" % use_desktop(desktop)) 262 | 263 | def find(callable, desktop=None): 264 | 265 | """ 266 | Find and return windows using the given 'callable' for the current desktop. 267 | If the optional 'desktop' parameter is specified then attempt to use that 268 | particular desktop environment's mechanisms to look for windows. 269 | """ 270 | 271 | return root(desktop).find(callable) 272 | 273 | # vim: tabstop=4 expandtab shiftwidth=4 274 | -------------------------------------------------------------------------------- /docs/src/markdown/_snippets/mathjax.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | -------------------------------------------------------------------------------- /docs/src/markdown/_snippets/refs.md: -------------------------------------------------------------------------------- 1 | [arithmatex]: https://facelessuser.github.io/pymdown-extensions/extensions/arithmatex/ 2 | [bps10]: https://github.com/bps10 3 | [critic]: http://criticmarkup.com/ 4 | [custom-fences]: https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#custom-fences 5 | [flow]: https://flowchart.js.org/ 6 | [gfm-api]: https://developer.github.com/v3/markdown/ 7 | [gfm-help]: https://help.github.com/articles/github-flavored-markdown/ 8 | [hexatrope]: https://github.com/hexatrope 9 | [home]: https://github.com/revolunet/sublimetext-markdown-preview 10 | [hozaka]: https://github.com/hozaka 11 | [issue]: https://github.com/revolunet/sublimetext-markdown-preview/issues 12 | [latest]: https://github.com/revolunet/sublimetext-markdown-preview/archive/master.zip 13 | [license]: http://revolunet.mit-license.org 14 | [live-reload]: https://packagecontrol.io/packages/LiveReload 15 | [package-control]: https://packagecontrol.io/ 16 | [pc-install]: https://packagecontrol.io/installation 17 | [ppvg-comment]: https://github.com/revolunet/sublimetext-markdown-preview/issues/78#issuecomment-15644727 18 | [pymd]: https://github.com/Python-Markdown/markdown 19 | [pymdownx-docs]: http://facelessuser.github.io/pymdown-extensions/usage_notes/ 20 | [pymdownx]: http://facelessuser.github.io/pymdown-extensions/ 21 | [sequence]: https://bramp.github.io/js-sequence-diagrams/ 22 | [settings]: https://github.com/revolunet/sublimetext-markdown-preview/blob/master/MarkdownPreview.sublime-settings 23 | [toc]: https://pythonhosted.org/Markdown/extensions/toc.html#usage 24 | [tommi]: https://github.com/tommi 25 | -------------------------------------------------------------------------------- /docs/src/markdown/changes.md: -------------------------------------------------------------------------------- 1 | # Changes 2 | 3 | ## 2.0.0 4 | 5 | Please read documentation as there have been big changes in this version which may require updates to your personal settings. 6 | 7 | * Do not vendor Python Markdown. Python Markdown will be acquired via the current markdown dependency. 8 | 9 | * Python Markdown configuration changes: 10 | 11 | * No more defining settings as `extension(option1=a,option2=b)`. Options will be defined as a dictionary. 12 | * You will have to define the full extension name: `markdown.extensions.codehilite`. This will allow you to import any extension you want outside of Markdown Preview. 13 | * New line to `
` conversion has been dropped from GitHub emulation as GitHub no longer does this. Ref issue #374. 14 | 15 | * Originally a couple pymdownx-extension extensions were ported over to this plugin to give a GitHub-ish feel to Markdown, these are no longer be included directly, but are included as a dependency. This will provide the latest versions, and also provide new extensions previously not included. Ref issue #378. 16 | 17 | * Drop ST2 so we no longer have to provide specially crafted Python Markdown versions when we try to upgrade. 18 | 19 | * Improve yaml front matter parsing: see issue #392. 20 | 21 | * Better UML JavaScript injection. 22 | 23 | * Link contributors in readme. 24 | 25 | * Remove "magic" Pygments configuration. User will now explicitly configure Pygments CSS injection separately. 26 | 27 | * Require explicit parser name moving forward instead of default, but provide a deprecation path for the short term. 28 | 29 | * Fix GitHub header ID generation. GitHub only lowercases ASCII chars. 30 | 31 | * Ensure default parser is Python Markdown, and enable auto-reload by default. 32 | 33 | * Hopefully better documentation. 34 | 35 | * Make flake8 compatible. 36 | 37 | * Fix outdated links. 38 | 39 | * Remove MatjJax and UML option in favor of a more generalized solution via the pre-existing `css` option. 40 | 41 | * Remove `embed_css_for_sublime_output` option in favor of more generalized `include_head` option. 42 | 43 | ## 1.4.3 44 | 45 | * Fix issue where Chrome prevents live reload. 46 | 47 | ## 1.4.0 48 | 49 | * `css` setting can now be an array and contain multiple CSS files (see settings file for more info). 50 | * Updated Github style to latest. 51 | 52 | ## 1.3.0 53 | 54 | * Now supports any markdown parser through a generalized method. Now you can map a binary to parser name via `markdown_binary_map`. Then use the parser name in `enabled_parsers` to use it. 55 | * Multimarkdown specific settings have been removed. Multimarkdown should now be configured via `markdown_binary_map` and `enabled_parsers`. 56 | * Upgraded to Python Markdown 2.6.4. 57 | * Removed internal PyYaml and Pygments. Markdown Preview now uses Package Control dependencies to obtain PyYaml and Pygments. 58 | * Update kbd CSS for Github. 59 | 60 | ## 1.0.3 61 | 62 | * The `messages.json` should OK for this time. 63 | 64 | ## 1.0.2 65 | 66 | * Fixes messages.json and changelog versions. 67 | 68 | ## 1.0.1 69 | 70 | * Removed markdown2 parser for its not well maintained and buggy. 71 | * Make Python Markdown parser as default. 72 | * Split the preview commands for *Python Markdown* parser and *Github Flavored Markdown* parser. 73 | * Add markdown file build support, build parser are config via the origin `"parser"` settings. 74 | * Add this changlog file for both developpers and users. 75 | * Add messages.json which make display of `README.md` and `CHANGES.md` 76 | * Try use `Markdown Extended.tmLanguage` for cheat sheet if you installed `Markdown Extended`. 77 | 78 | ## 1.0.0 79 | 80 | * Support for ST3. 81 | * Added Python Markdown parser. 82 | * CSS search first in markdown file directory and the the build-in. 83 | -------------------------------------------------------------------------------- /docs/src/markdown/extras.md: -------------------------------------------------------------------------------- 1 | # Extras 2 | 3 | ## MathJax Support 4 | 5 | To render Tex style math in Markdown, you can use the default MathJax configuration that is included with Markdown Preview or create and reference your own. 6 | 7 | When using Python Markdown (the `markdown` parser), it is recommended to use something like the extension [`pymdownx.arithmatex`][arithmatex] as it ensures that math notation is preserved in the Markdown conversion process. GitHub (the `github` parser) does not have such an extension, so you might have to escape accordingly. 8 | 9 | In this example, we will try to show a generalized approach that should work when using Python Markdown with `pymdownx.arithmatex` or GitHub (though preservation of math in GitHub may or may not be problematic). 10 | 11 | Markdown Preview provides a generalized script in `Markdown Preview/js/math_config.js`. It searches for `#!tex $...$`, `#!tex $$...$$`, `#!tex \(...\)`, and `#!tex \[...\]`. You can change this to only target what you want by creating your own. 12 | 13 | To load MathJax support, simply include the MathJax library along with the math config file provided by this extension. You are free to provide your own if you'd like to tweak the configuration: 14 | 15 | ```js 16 | "js": [ 17 | "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js", 18 | "res://Markdown Preview/js/math_config.js" 19 | ] 20 | ``` 21 | 22 | If you are using `pymdownx.arithmatex` you can configure like so to take advantage of the generalized configuration. You are also free to customize Arithmatex to target only what you want and output in the different forms. Check out Arithmatex documentation for more info. 23 | 24 | ```js 25 | "markdown_extensions": { 26 | "pymdownx.arithmatex": { 27 | "generic": true 28 | } 29 | } 30 | ``` 31 | 32 | ## UML Support 33 | 34 | If you are using the extension [SuperFences extension][superfences], it has an option to create special, custom fences. By default, it specifies `flow` and `sequence` languages to generate special code blocks that JavaScript can be applied to later to create UML diagrams: see [documentation][custom-fences] for more info. Assuming you are using SuperFences, you can include the following libraries to transform `sequence` and `flow` blocks using [js-sequence-diagrams][sequence] and [flowchart.js][flow] respectively. 35 | 36 | ```js 37 | "js": [ 38 | // Required libraries to transform UML notation 39 | "https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js", 40 | "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js", 41 | "https://cdnjs.cloudflare.com/ajax/libs/js-sequence-diagrams/1.0.6/sequence-diagram-min.js", 42 | "https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.6.5/flowchart.min.js", 43 | 44 | // This library applies the above libraries to the fenced code blocks `flow` and `sequence`. 45 | "res://Markdown Preview/js/uml.js" 46 | ] 47 | ``` 48 | 49 | --8<-- "refs.md" 50 | -------------------------------------------------------------------------------- /docs/src/markdown/images/sublimetext-markdown-preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/revolunet/sublimetext-markdown-preview/154bdd63f27970dd4c775c5c57810d7f18c64ea5/docs/src/markdown/images/sublimetext-markdown-preview.gif -------------------------------------------------------------------------------- /docs/src/markdown/index.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Preview and build your markdown files quickly in your web browser. 4 | 5 | You can use the builtin [Python Markdown][pymd] parser (offline) or use the [GitHub Markdown API][gfm-api] (online) for the conversion. 6 | 7 | !!! note 8 | If you choose the GitHub API for conversion (set `parser` to `github` in your settings), your code will be sent through HTTPS to GitHub for live conversion. You'll have [Github Flavored Markdown][gfm-help], syntax highlighting and EMOJI support for free :heart: :gift:. If you make more than 60 calls a day, be sure to set your GitHub API key in the settings :smile:. 9 | 10 | ## Features 11 | 12 | - Markdown preview using the [python-markdown][pymd] with syntax highlighting via Pygments and optional 3rd party extensions ([pymdown-extensions][pymdownx-docs] included by default). 13 | - Markdown previews via the Github API. 14 | - Ability use other external Markdown parsers. 15 | - Build markdown file using Sublime Text build system. 16 | - Browser preview auto reload on save if you have the [LiveReload plugin][live-reload] installed. 17 | - Configurable CSS and JavaScript assets with overriding if needed. 18 | - YAML support thanks to [@tommi][tommi]. 19 | - Clipboard selection and copy to clipboard thanks to [@hexatrope][hexatrope]. 20 | - MathJax support : $\frac{\pi}{2}$ thanks to [@bps10][bps10]. 21 | - HTML template customization thanks to [@hozaka][hozaka]. 22 | - Embed images as base64. 23 | - Strip out MultiMarkdown CriticMarkup. 24 | 25 | ## Support 26 | 27 | - Any bugs about Markdown Preview please feel free to report [here][issue]. 28 | - And you are welcome to fork and submit pull requests. 29 | 30 | ## Attribution 31 | 32 | Markdown Preview contains a stripped down version of font awesome that is included in the default non-GitHub CSS. It contains only the icons we currently use. 33 | 34 | https://fontawesome.com/license 35 | 36 | ## License 37 | 38 | The code is available at [GitHub][home] under the [MIT license][license]. 39 | 40 | --8<-- "refs.md" 41 | --8<-- "mathjax.md" 42 | -------------------------------------------------------------------------------- /docs/src/markdown/install.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Using [Package Control][package-control] (*Recommended*) 4 | 5 | We recommend installing via [Package Control][package-control]. 6 | 7 | 1. [Install][pc-install] Package Control if you haven't yet. 8 | 2. Use the shortcut ++cmd+shift+p then select `Package Control: Install Package`. 9 | 3. Look for and select `Markdown Preview`. 10 | 11 | --8<-- "refs.md" 12 | -------------------------------------------------------------------------------- /docs/src/markdown/license.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Copyright © 2015 Julien Bouquillon, revolunet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /docs/src/markdown/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | !!! info 4 | When referring to settings, we are referring to the settings found at `Preferences`->`Package Settings`->`Markdown Preview`. 5 | 6 | - `Settings - User` is where you change your settings for Markdown Preview. 7 | - `Settings - Default` is a good reference with detailed descriptions for each setting. 8 | 9 | ## To preview 10 | 11 | - Optionally select some of your markdown for conversion. 12 | - Use the shortcut ++cmd+shift+p++ then select `Markdown Preview` to show the follow commands (you will be prompted to select which parser you prefer): 13 | - Markdown Preview: Preview in Browser 14 | - Markdown Preview: Export HTML in Sublime Text 15 | - Markdown Preview: Copy to Clipboard 16 | - Markdown Preview: Open Markdown Cheat sheet 17 | 18 | ![Usage Demo](images/sublimetext-markdown-preview.gif) 19 | 20 | - Or bind some shortcut in your user key binding, go to `Preferences --> Keybindings` then add to the User map: 21 | 22 | For a specific parser and target: 23 | 24 | ```js 25 | { "keys": ["alt+m"], "command": "markdown_preview", "args": {"target": "browser", "parser":"markdown"} }, 26 | ``` 27 | 28 | To bring up the quick panel to select enabled parsers for a given target: 29 | 30 | ```js 31 | { "keys": ["alt+m"], "command": "markdown_preview_select", "args": {"target": "browser"} }, 32 | ``` 33 | 34 | - If you want to control which browser the preview is opened in, you can edit the `browser` option in the settings file: 35 | 36 | ```js 37 | /* 38 | Sets the default opener for HTML files 39 | 40 | default - Use the system default HTML viewer 41 | other - Set a full path to any executable. ex: /Applications/Google Chrome Canary.app or /Applications/Firefox.app 42 | */ 43 | "browser": "default", 44 | ``` 45 | 46 | ## Custom Templates 47 | 48 | By default, Markdown Preview uses a simple template, but you can use your own custom template with the setting `html_template`. If you wish to not include the default stylesheets, just remove them from the `css` option. 49 | 50 | ```js 51 | /* 52 | Specify a HTML template file to render your markdown within. 53 | 54 | Available place holders in HTML template: 55 | {{ HEAD }} - would be replaced by generated stylesheets, javascripts enabled above 56 | {{ BODY }} - would be replaced by HTML converted from markdown 57 | 58 | By setting "skip_default_stylesheet" to true you can use the styles only in your HTML 59 | template. In most cases you should turn this setting on to have a full-featured design. 60 | 61 | Refer to 'customized-template-sample.html' as a show case. 62 | */ 63 | "html_template": "/ABS_PATH_TO_A_HTML_FILE", 64 | ``` 65 | 66 | ## LiveReload 67 | 68 | To get live updates while editing a file after preview, you need to do the following: 69 | 70 | 1. Enable the `enable_autoreload` setting in `MarkdownPreview.sublime-settings`. 71 | ```js 72 | /* 73 | Enable auto-reloaded on save. Will not work if GitHub parser is used without oauth key specified. 74 | */ 75 | "enable_autoreload": true, 76 | ``` 77 | 2. Install [LiveReload][7] package from Package Control. 78 | 3. Restart. 79 | 4. Open the command palette and select the command `LiveReload: Enable/disable plug-ins`. 80 | 5. Select `Simple Reload with delay (400ms)`. It is possible you can get away with `Simple Reload`, but some experience an issue where they are one rev behind when using `Simple Reload`. 81 | 6. Edit document and enjoy live reload. 82 | 83 | You don't need to enable `Simple Reload` on every file as it is done globally; it can be turned on or off as needed. From now on, files should auto-reload when you open them in the browser unless you disable `Simple Reload`. 84 | 85 | ## Preview Path Conversion 86 | 87 | In the generated previews, paths are converted so that images and other links work properly. By default, paths are converted to absolute paths, but you can use relative if desired as well. Image paths can also be changed to inject embedded base 64 images (only for local images). Path handling is controlled by the following two settings: 88 | 89 | ```js 90 | /* 91 | Sets how image paths are handled. 92 | Setting is a string value: (absolute | relative | base64 | none) 93 | absolute: converts relative local paths to absolute 94 | relative: converts relative local paths to a path relative to the 95 | HTML output 96 | base64: coverts the local file to base64 and embeds it in the HTML 97 | none: does nothing 98 | */ 99 | "image_path_conversion": "absolute", 100 | 101 | /* 102 | Sets how file paths are handled. 103 | Setting is a string value: (absolute | relative | none) 104 | absolute: converts relative local paths to absolute 105 | relative: converts relative local paths to a path relative to the 106 | HTML output 107 | none: does nothing 108 | */ 109 | "file_path_conversions": "absolute", 110 | ``` 111 | 112 | ## Preview Temp Location 113 | 114 | By default, previews are generated in the OSs default temp location, but you can specify your own custom temp location via the `path_tempfile` option: 115 | 116 | ```js 117 | /* 118 | Sets a custom temporary folder for MarkdownPreview-generated HTML files. Useful if you're 119 | using LiveReload and don't want to use the OS default. The directory will be created if it 120 | doesn't exist. Relative paths are supported, and are checked against `os.path.isabs`, see 121 | doc: http://docs.python.org/3/library/os.path.html#os.path.isabs 122 | 123 | Examples: /tmp/custom_folder (Linux/OSX - absolute path) 124 | C:/TEMP/MYNOTES 125 | C:\\TEMP\\MYNOTES (Windows - absolute path, forward slash or escaped back slash) 126 | build (All OS - relative path, current dir) 127 | ../build (Linux/OSX - relative path, in parent dir) 128 | ..\\build (Windows - relative path, in parent dir) 129 | */ 130 | "path_tempfile": "/tmp/my_notes", 131 | ``` 132 | 133 | ## Enabling Other External Markdown Parsers 134 | 135 | External parser commands and arguments should first be mapped to a name. Each binary value must be an array with the path to the binary being first, followed by flags and options as individual indexes in the array. 136 | 137 | ```js 138 | "markdown_binary_map": { 139 | "multimarkdown": ["/usr/local/bin/multimarkdown", "--some-option", "some-value"] 140 | }, 141 | ``` 142 | 143 | Then the name can be placed in `enabled_parsers` to enable use of the new parser. 144 | 145 | ```js 146 | "enabled_parsers": ["markdown", "github", "multimarkdown"], 147 | ``` 148 | 149 | ## Configuring Python Markdown Extensions 150 | 151 | Python Markdown comes with a number of extensions and can also use a number of 3rd party extensions. To configure Markdown Preview with extensions, use the `markdown_extensions` setting. 152 | 153 | `markdown_extensions` is a setting that contains an array of extensions in the format of their import path. For instance, the Toc (Table of Contents) extension is found in the Markdown Package at `markdown.extensions.toc`. This is according to Python Markdown [documentation][toc]. All extensions must be specified this way. 154 | 155 | ```js 156 | "markdown_extensions": [ 157 | "markdown.extensions.toc" 158 | ] 159 | ``` 160 | 161 | To configure an extension, make the entry a dictionary. In this example, we want to turn on Toc's permalink feature: 162 | 163 | ```js 164 | "markdown_extensions": [ 165 | { 166 | "markdown.extensions.toc": { 167 | "permalink": true 168 | } 169 | } 170 | ] 171 | ``` 172 | 173 | You can configure extension options with strings, booleans, integers, floats, etc. But sometimes, an extension can take a function. Functions are not part of the JSON spec. Luckily, support has been added with the following syntax: 174 | 175 | To specify a function, create an object whose key is named `!!python/name`, and whose value is the import path of the function. This syntax was picked to be similar to PyYaml's syntax which is used for the Markdown frontmatter. 176 | 177 | So let's pretend we didn't like Toc's default slugify `markdown.extensions.headerid.slugify`, and instead wanted to use PyMdown Extensions' slugify `pymdownx.slugs.uslugify`. We could specify the new slugify function with the following syntax: 178 | 179 | ```js 180 | "markdown_extensions": [ 181 | { 182 | "markdown.extensions.toc": { 183 | "slugify": {"!!python/name", "pymdownx.slugs.uslugify"} 184 | } 185 | } 186 | ] 187 | ``` 188 | 189 | Compare to the PyYaml format: 190 | 191 | ```yml 192 | markdown_extensions: 193 | - markdown.extensions.toc: 194 | slugify: !!python/name:pymdownx.slugs.uslugify 195 | ``` 196 | 197 | ## To build 198 | 199 | Just use ctrl+B (Windows/Linux) or cmd+B (Mac) to build current file. 200 | 201 | You can configure the build action by using the `build_action` setting. 202 | 203 | ```js 204 | /* 205 | By default, Markdown Preview builds the HTML in the source directory. 206 | It expects the file to exist on disk. It pops up the build output panel etc. 207 | 208 | If you wish to override this behavior, you can change "build_action" 209 | 210 | build - The default build behavior. 211 | browser - Preview the file in your browser. 212 | clipboard - Copy the HTML output to the clipboard. 213 | sublime - Export the HTML to a Sublime tab. 214 | save - Run the normal save command that outputs to the source directory. 215 | It will also prompt for "save as" if the file does not exit on disk. 216 | 217 | All the build options use the default parser defined above in "parser" 218 | */ 219 | "build_action": "build", 220 | ``` 221 | 222 | And the parser that is used when building is set in the `parser` setting: 223 | 224 | ```js 225 | /* 226 | Sets the parser used for building markdown to HTML. 227 | 228 | NOTE: The parser setting is not for the preview commands now. 229 | The previews have separate commands for each parser markdown. 230 | 231 | Warning for github API: if you have a ST2 linux build, Python is not built with SSL so it may not work 232 | 233 | default - The current default parser is python-markdown parser. 234 | markdown - Use the built-in python-markdown parser 235 | github - Use the github API to convert markdown, so you can use GitHub flavored Markdown, see https://help.github.com/articles/github-flavored-markdown/ 236 | */ 237 | "parser": "markdown", 238 | ``` 239 | 240 | When building, a panel will be opened showing build information. This can be disabled by setting `show_panel_on_build` to `false`: 241 | 242 | ```js 243 | /* do we show the panel when building with CMD+B */ 244 | "show_panel_on_build": true, 245 | ``` 246 | 247 | ## Configuring Pygments 248 | 249 | If you add the codehilite extension manually in the enabled extensions, you can override some of the default settings. 250 | 251 | * Turn language guessing *on* or *off* (*on* will highlight fenced blocks even if you don't specify a language): 252 | 253 | ```js 254 | "markdown_extensions": [ 255 | "codehilite": { 256 | "guess_lang": false 257 | } 258 | ] 259 | ``` 260 | 261 | * Show line numbers: 262 | 263 | ```js 264 | "markdown_extensions": [ 265 | "codehilite": { 266 | "linenums": false 267 | } 268 | ] 269 | ``` 270 | 271 | * Change the higlight theme: 272 | 273 | ```js 274 | "markdown_extensions": [ 275 | "codehilite": { 276 | "pygments_style": "emacs" 277 | } 278 | ] 279 | ``` 280 | 281 | * Inline the CSS: 282 | 283 | ```js 284 | "markdown_extensions": [ 285 | "codehilite": { 286 | "noclasses": true 287 | } 288 | ] 289 | ``` 290 | 291 | * Use multiple: 292 | ```js 293 | "markdown_extensions": [ 294 | "codehilite": { 295 | "linenums": true, 296 | "pygments_style": "emacs" 297 | } 298 | ] 299 | ``` 300 | 301 | The `codehiite` extension's `pygments_style` option is only useful if you are using `noclasses` which writes the styles directly to the HTML tags via the `style` attribute. Normally, we just inject CSS generated by Pygments which is the default behavior. Whether the CSS injection occurs, the Pygments' style that is used, and the CSS class that is used for code blocks can all be controlled with the following options: 302 | 303 | ```js 304 | /* 305 | If Pygments is being used, you may want to inject one of the Pygment styles provided into the HTML. 306 | If so, enable this. 307 | */ 308 | "pygments_inject_css": true, 309 | 310 | /* 311 | Name of the Pygments style to inject. Available styles are the styles provided by pygments 312 | plus "github" and "github2014". 313 | */ 314 | "pygments_style": "github", 315 | 316 | /* 317 | This is the class to prepend to the pygments CSS styles. Make sure it matches whatever class(es) 318 | you've specified in the extension that controls Pygments highlighting. CodeHilite's default is 319 | "codehilite". 320 | */ 321 | "pygments_css_class": "codehilite", 322 | ``` 323 | 324 | See [codehilte page](https://python-markdown.github.io/extensions/code_hilite) for more info. 325 | 326 | ## Meta Data Support 327 | 328 | When the `meta` extension is enabled (https://python-markdown.github.io/extensions/meta_data), the results will be written to the HTML head in the form ``. `title` is the one exception, and its content will be written to the title tag in the HTML head. 329 | 330 | ## YAML Frontmatter Support 331 | 332 | YAML frontmatter can be stripped out and read when `strip_yaml_front_matter` is set to `true` in the settings file. In general the, the frontmatter is handled the same as [meta data](#meta-data-support), but if both exist in a file, the YAML keys will override the `meta` extension keys. There are a few special key names that won't be handled as HTML meta data. 333 | 334 | ```js 335 | /* 336 | Strips the YAML front matter header and converts title to a heading 337 | */ 338 | "strip_yaml_front_matter": false, 339 | ``` 340 | 341 | ### Special YAML Key Names 342 | 343 | YAML frontmatter has a few special key names that are used that will not be handled as meta data: 344 | 345 | - **basepath**: An absolute path to configure the relative paths for images etc. (for when the markdown is supposed to reference images in a different location.) 346 | - **references**: Can take a file path or an array of file paths for separate markdown files containing references, footnotes, etc. Can be an absolute path or relative path. Relative paths first use the source file's directory, and if the file cannot be found, it will use the `basepath` setting. 347 | - **destination**: This is an absolute file path or relative file path for when the markdown is saved to html via the build command or the `Save to HTML` command. Relative paths first use the source file's directory, and if the file cannot be found, it will use the `basepath` setting. 348 | - **settings**: This is a dictionary where you can override settings that are in the settings file. 349 | 350 | ```yaml 351 | --- 352 | # Builtin values 353 | references: 354 | - references.md 355 | - abbreviations.md 356 | - footnotes.md 357 | 358 | destination: destination.html 359 | 360 | # Meta Data 361 | title: Test Page 362 | author: 363 | - John Doe 364 | - Jane Doe 365 | 366 | # Settings overrides 367 | settings: 368 | enable_uml: true 369 | markdown_extensions: 370 | - markdown.extensions.footnotes 371 | - markdown.extensions.attr_list 372 | - markdown.extensions.def_list 373 | - markdown.extensions.tables 374 | - markdown.extensions.abbr 375 | - markdown.extensions.toc 376 | - markdown.extensions.smarty 377 | - markdown.extensions.meta 378 | - markdown.extensions.wikilinks 379 | - markdown.extensions.admonition 380 | - markdown.extensions.codehilite: 381 | guess_lang: false 382 | pygments_style: github 383 | - pymdownx.extrarawhtml 384 | - pymdownx.progressbar 385 | - pymdownx.github 386 | - pymdownx.caret: 387 | superscript: false 388 | --- 389 | ``` 390 | 391 | ## Parsing Github Flavored Markdown 392 | 393 | Github Flavored Mardown (GFM) is a very popular markdown. Markdown Preview can actually handle them in a couple of ways: online and offline. 394 | 395 | ### Online 396 | 397 | Parsing GFM using the online method requires using the Github API as the parser. It may also require setting `github_mode` to `gfm` to get things like tasklists to render properly. 398 | 399 | ```js 400 | /* 401 | Default mode for the github Markdown parser : markdown (documents) or gfm (comments) 402 | see http://developer.github.com/v3/markdown/#render-an-arbitrary-markdown-document 403 | */ 404 | "github_mode": "markdown", 405 | ``` 406 | 407 | Using the GitHub API without an oauth key is limited to so many calls. After the limit is reached, the GitHub API will deny further calls until after a set limit of time. To avoid this issue, you can set your API key in the settings as follows: 408 | 409 | ```js 410 | /* 411 | Uses an OAuth token when parsing markdown with GitHub API. To create one for Markdown Preview, see https://help.github.com/articles/creating-an-oauth-token-for-command-line-use. 412 | Warn: this secret *must not be shared* with anyone and at least you should create it with minimal scopes for security reasons. 413 | */ 414 | "github_oauth_token": "secret", 415 | ``` 416 | 417 | The GitHub API only inserts IDs for headers when `github_mode` is `markdown`, but it doesn't quite generate the way that GitHub does in your project's readmes on the site. This makes it so the GitHub CSS doesn't create the clickable anchors. So when `github_mode` is `markdown`, you can have Markdown Preview insert the ids properly so the CSS works with the following option: 418 | 419 | ```js 420 | /* 421 | Enables a post process to inject header ids to ensure hrefs to headers work 422 | */ 423 | "github_inject_header_ids": true, 424 | ``` 425 | 426 | ### Offline 427 | 428 | By default almost all extensions are enabled to help with a GitHub-ish feel, but there are some tweaks needed to get the full experience. 429 | 430 | GFM does not auto guess language in fenced blocks, but Markdown Preview does this by default. You can fix this in one of two ways: 431 | 432 | 1. Disable auto language guessing in the settings file `"guess_language": false,` 433 | 2. Or if you are manually defining extensions: 434 | 435 | ```js 436 | "markdown_extensions": [ 437 | "codehilite": { 438 | "guess_lang": false, 439 | "pygments_style": "github" 440 | } 441 | ] 442 | ``` 443 | 444 | As mentioned earlier, a number of extensions are included by default. You can remove ones that are not part of GFM. 445 | 446 | ## Including CSS 447 | 448 | By default Markdown Preview includes a default CSS via the `css` setting. It uses the special keyword `default` to represent the default CSS. 449 | 450 | ```js 451 | "css": ["default"], 452 | ``` 453 | 454 | You can include whatever CSS you want, and even remove the `default` if you like. It can take URLs or file paths. If you want to add a resource that is contained within a Sublime Package (like the Markdown Preview package itself), you can use the special URL of `res:////file.css`. Using the `res://` format will allow Markdown Preview to resolve the resource when it is in a package that is zipped and unzipped. 455 | 456 | ### Override CSS by File Type 457 | 458 | You can also override the default CSS with special file specific CSS. This CSS does not replace the default, but will append CSS for a supported file type after the conventional CSS. 459 | 460 | So assuming the following configuration: 461 | 462 | ```js 463 | "css": ["default"], 464 | // File must be of one type below 465 | "markdown_filetypes": [".md", ".markdown", ".mdown"], 466 | ``` 467 | 468 | We could enable the following: 469 | 470 | ```js 471 | "allow_css_overrides": true, 472 | ``` 473 | 474 | Then if we have a file `filename.md` and a CSS in the same directory `filename.css`, that CSS will be applied to that file. 475 | 476 | ### Including HTML HEAD 477 | 478 | By default, the head is always included in the HTML output. This includes the CSS, JavaScript, etc. If for some reason you need to omit the HEAD, you can by modifying the `include_head` option. Just remove the target that you wish to omit the head in. The option `build` specifically refers to when `build_action` is set to `build` in the settings. 479 | 480 | ```js 481 | /* do we include the CSS when outputting HTML? */ 482 | "include_head": ["build", "browser", "sublime", "clipboard", "save"] 483 | ``` 484 | 485 | ## Including JavaScript 486 | 487 | JavaScript files can be included via the `js` setting. It is a list and can take file paths or URLs. If you want to add a resource that is contained within a Sublime Package (like the Markdown Preview package itself), you can use the special URL of `res:////file.js`. Using the `res://` format will allow Markdown Preview to resolve the resource when it is in a package that is zipped and unzipped. 488 | 489 | ```js 490 | "js": [], 491 | ``` 492 | 493 | ## CriticMarkup 494 | 495 | Python Markdown can strip/apply out [CriticMarkup][critic] syntax if desired. Simply enable the following option: 496 | 497 | ```js 498 | /* 499 | Sets how multimarkdown critic marks are handled. 500 | Setting is a string value: (accept | reject | none) 501 | accept: Accepts the proposed inserts and deletions (comments etc. are discarded) 502 | reject: Rejects the proposed inserts and deletions (comments etc. are discarded) 503 | none: does nothing 504 | 505 | Critic marks only affects "github" and "markdown" (Python Markdown). 506 | */ 507 | "strip_critic_marks": "none", 508 | ``` 509 | 510 | ### Simple HTML Output 511 | 512 | Some people may desire a stripped down output on occasions that does not include HTML headers, inline styles, and IDs. Markdown Preview has a mode that will strip out these things and omit using a template. This mode can be enabled via the the `html_simple` option: 513 | 514 | ```js 515 | /* 516 | Sets HTML output to a simple form: 517 | - No head 518 | - No body tags 519 | - ids, classes, and style are stripped out 520 | - Just bare minimum HTML tags and attributes 521 | - extension modifications included 522 | */ 523 | "html_simple": false, 524 | ``` 525 | 526 | --8<-- "refs.md" -------------------------------------------------------------------------------- /docs/theme/extra-d04c85ed4a.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.md-typeset .magiclink:before{position:relative;padding-right:.25rem;font-family:FontAwesome;-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;font-weight:400}.md-typeset .magiclink-repository.magiclink-github:before{content:""}.md-typeset .magiclink-repository.magiclink-gitlab:before{content:""}.md-typeset .magiclink-repository.magiclink-bitbucket:before{content:""}.md-typeset .keys kbd:after,.md-typeset .keys kbd:before{position:relative;margin:0;color:#bdbdbd;font-family:sans-serif;-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;font-weight:400}.md-typeset .keys span{padding:0 .2rem;color:#bdbdbd}.md-typeset .keys .key-backspace:before{padding-left:.2rem;content:"←"}.md-typeset .keys .key-command:before{padding-left:.2rem;content:"⌘"}.md-typeset .keys .key-windows:before{padding-left:.2rem;content:"⊞"}.md-typeset .keys .key-caps-lock:before{padding-left:.2rem;content:"⇪"}.md-typeset .keys .key-control:before{padding-left:.2rem;content:"⌃"}.md-typeset .keys .key-meta:before{padding-left:.2rem;content:"◆"}.md-typeset .keys .key-shift:before{padding-left:.2rem;content:"⇧"}.md-typeset .keys .key-option:before{padding-left:.2rem;content:"⌥"}.md-typeset .keys .key-tab:after{padding-left:.2rem;content:"↹"}.md-typeset .keys .key-num-enter:after{padding-left:.2rem;content:"↵"}.md-typeset .keys .key-enter:after{padding-left:.2rem;content:"↩"}.md-typeset .admonition.settings,.md-typeset details.settings{border-left:.4rem solid #a0f}.md-typeset .admonition.settings>.admonition-title,.md-typeset details.settings>.admonition-title,.md-typeset details.settings>summary{border-bottom:.1rem solid rgba(170,0,255,.1);background-color:rgba(170,0,255,.1)}.md-typeset .admonition.settings>.admonition-title:before,.md-typeset details.settings>.admonition-title:before,.md-typeset details.settings>summary:before{color:#a0f;content:"settings"}.md-typeset .uml-flowchart,.md-typeset .uml-sequence-diagram{width:100%;padding:1rem 0;overflow:auto}.md-typeset .uml-flowchart svg,.md-typeset .uml-sequence-diagram svg{max-width:none}.md-typeset a>code{margin:0 .29412em;padding:.07353em 0;border-radius:.2rem;background-color:hsla(0,0%,93%,.5);box-shadow:.29412em 0 0 hsla(0,0%,93%,.5),-.29412em 0 0 hsla(0,0%,93%,.5);-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset .linenodiv .special{color:#fff;font-weight:800}.md-typeset td code{word-break:normal}.md-typeset .codehilite .hll,.md-typeset .highlight .hll{display:inline}.md-typeset .headerlink{font:normal 400 2rem Material Icons;vertical-align:middle}.md-typeset h2 .headerlink{margin-top:-.4rem}.md-typeset h3 .headerlink{margin-top:-.3rem}.md-typeset h4 .headerlink,.md-typeset h5 .headerlink,.md-typeset h6 .headerlink{margin-top:-.2rem}.md-typeset .progress-label{position:absolute;width:100%;margin:0;color:rgba(0,0,0,.5);font-weight:700;line-height:1.4rem;text-align:center;white-space:nowrap}.md-typeset .progress-bar{height:1.2rem;float:left;background-color:#2979ff}.md-typeset .candystripe-animate .progress-bar{-webkit-animation:a 3s linear infinite;animation:a 3s linear infinite}.md-typeset .progress{display:block;position:relative;width:100%;height:1.2rem;margin:.5rem 0;background-color:#eee}.md-typeset .progress.thin{height:.4rem;margin-top:.9rem}.md-typeset .progress.thin .progress-label{margin-top:-.4rem}.md-typeset .progress.thin .progress-bar{height:.4rem}.md-typeset .progress.candystripe .progress-bar{background-image:linear-gradient(135deg,hsla(0,0%,100%,.8) 27%,transparent 0,transparent 52%,hsla(0,0%,100%,.8) 0,hsla(0,0%,100%,.8) 77%,transparent 0,transparent);background-size:2rem 2rem}.md-typeset .progress-80plus .progress-bar,.md-typeset .progress-100plus .progress-bar{background-color:#00e676}.md-typeset .progress-60plus .progress-bar{background-color:#fbc02d}.md-typeset .progress-40plus .progress-bar{background-color:#ff9100}.md-typeset .progress-20plus .progress-bar{background-color:#ff5252}.md-typeset .progress-0plus .progress-bar{background-color:#ff1744}.md-typeset .progress.note .progress-bar{background-color:#2979ff}.md-typeset .progress.summary .progress-bar{background-color:#00b0ff}.md-typeset .progress.tip .progress-bar{background-color:#00bfa5}.md-typeset .progress.success .progress-bar{background-color:#00e676}.md-typeset .progress.warning .progress-bar{background-color:#ff9100}.md-typeset .progress.failure .progress-bar{background-color:#ff5252}.md-typeset .progress.danger .progress-bar{background-color:#ff1744}.md-typeset .progress.bug .progress-bar{background-color:#f50057}.md-typeset .progress.quote .progress-bar{background-color:#9e9e9e}@-webkit-keyframes a{0%{background-position:0 0}to{background-position:6rem 0}}@keyframes a{0%{background-position:0 0}to{background-position:6rem 0}}.md-footer .md-footer-custom-text{color:hsla(0,0%,100%,.3)}@media only screen and (min-width:76.1876em){.md-typeset .headerlink{margin-left:-2.4rem;float:left}.md-typeset h2 .headerlink{margin-top:.6rem}.md-typeset h3 .headerlink{margin-top:.4rem}.md-typeset h4 .headerlink{margin-top:.2rem}.md-typeset h5 .headerlink,.md-typeset h6 .headerlink{margin-top:0}} -------------------------------------------------------------------------------- /docs/theme/extra-d8800ea088.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";var e=function(e,t,n){for(var o=function(e){for(var t="",n=0;n 15 | var text = ""; 16 | for (var j = 0; j < parent.childNodes.length; j++) { 17 | var subEl = parent.childNodes[j]; 18 | if (subEl.tagName.toLowerCase() === "code") { 19 | for (var k = 0; k < subEl.childNodes.length; k++) { 20 | var child = subEl.childNodes[k]; 21 | var whitespace = /^\s*$/; 22 | if (child.nodeName === "#text" && !whitespace.test(child.nodeValue)) { 23 | text = child.nodeValue; 24 | break; 25 | } 26 | } 27 | } 28 | } 29 | return text; 30 | }; 31 | 32 | var getFromDiv = function getFromDiv(parent) { 33 | // Handles
34 | return parent.textContent || parent.innerText; 35 | }; 36 | 37 | // Change article to whatever element your main Markdown content lives. 38 | var article = document.querySelectorAll("article"); 39 | var blocks = document.querySelectorAll("pre." + className + ",div." + className 40 | 41 | // Is there a settings object? 42 | );var config = settings === void 0 ? {} : settings; 43 | 44 | // Find the UML source element and get the text 45 | for (var i = 0; i < blocks.length; i++) { 46 | var parentEl = blocks[i]; 47 | var el = document.createElement("div"); 48 | el.className = className; 49 | el.style.visibility = "hidden"; 50 | el.style.position = "absolute"; 51 | 52 | var text = parentEl.tagName.toLowerCase() === "pre" ? getFromCode(parentEl) : getFromDiv(parentEl 53 | 54 | // Insert our new div at the end of our content to get general 55 | // typset and page sizes as our parent might be `display:none` 56 | // keeping us from getting the right sizes for our SVG. 57 | // Our new div will be hidden via "visibility" and take no space 58 | // via `poistion: absolute`. When we are all done, use the 59 | // original node as a reference to insert our SVG back 60 | // into the proper place, and then make our SVG visilbe again. 61 | // Lastly, clean up the old node. 62 | ); 63 | article[0].appendChild(el); 64 | var diagram = converter.parse(text); 65 | diagram.drawSVG(el, config); 66 | el.style.visibility = "visible"; 67 | el.style.position = "static"; 68 | parentEl.parentNode.insertBefore(el, parentEl); 69 | parentEl.parentNode.removeChild(parentEl); 70 | } 71 | }); 72 | 73 | (function () { 74 | var onReady = function onReady(fn) { 75 | if (document.addEventListener) { 76 | document.addEventListener("DOMContentLoaded", fn); 77 | } else { 78 | document.attachEvent("onreadystatechange", function () { 79 | if (document.readyState === "interactive") { 80 | fn(); 81 | } 82 | }); 83 | } 84 | }; 85 | 86 | onReady(function () { 87 | if (typeof flowchart !== "undefined") { 88 | uml(flowchart, "uml-flowchart"); 89 | } 90 | 91 | if (typeof Diagram !== "undefined") { 92 | uml(Diagram, "uml-sequence-diagram", { theme: "simple" }); 93 | } 94 | }); 95 | })(); 96 | 97 | }()); 98 | -------------------------------------------------------------------------------- /markdown_settings.py: -------------------------------------------------------------------------------- 1 | """Markdown Preview settings handler.""" 2 | from __future__ import unicode_literals 3 | import sublime 4 | import os 5 | import sys 6 | import re 7 | import json 8 | import importlib 9 | 10 | BUILTIN_KEYS = ('basepath', 'references', 'destination') 11 | 12 | 13 | def extended_decode(d): 14 | """Decode python functions in JSON.""" 15 | if '!!python/name' in d: 16 | parts = d["!!python/name"].split('.') 17 | function = parts[-1] 18 | module = '.'.join(parts[:-1]) 19 | return getattr(importlib.import_module(module), function) 20 | return d 21 | 22 | 23 | class Settings(object): 24 | """Settings handler.""" 25 | 26 | def __init__(self, settings_file, file_name): 27 | """Initialize.""" 28 | self.file_name = file_name 29 | self._sub_settings = sublime.load_settings(settings_file) 30 | self._overrides = { 31 | "builtin": { 32 | "references": [], 33 | "basepath": self.get_base_path(None) 34 | }, 35 | "meta": {} 36 | } 37 | 38 | def parse_md_ext(self): 39 | """Parse Markdown extensions.""" 40 | extensions = self._sub_settings.get('markdown_extensions', {}) 41 | return json.loads(json.dumps(extensions), object_hook=extended_decode) 42 | 43 | def get(self, key, default=None): 44 | """ 45 | Get method for the settings object. 46 | 47 | First check if there is an override. 48 | """ 49 | if key in self._overrides: 50 | return self._overrides[key] 51 | else: 52 | if key == 'markdown_extensions': 53 | return self.parse_md_ext() 54 | else: 55 | return self._sub_settings.get(key, default) 56 | 57 | def set(self, key, value): 58 | """ 59 | Set method for the settings object. 60 | 61 | Setting will add to overrides. 62 | """ 63 | self._overrides[key] = value 64 | 65 | def has(self, key): 66 | """ 67 | Check if key is present. 68 | 69 | Check in overrides first. 70 | """ 71 | found = key in self._overrides 72 | if not found: 73 | found = self._sub_settings.has(key) 74 | return found 75 | 76 | def is_abs(self, pth): 77 | """Check if path is an absolute path.""" 78 | absolute = False 79 | if pth is not None: 80 | if sys.platform.startswith('win'): 81 | re_win_drive = re.compile(r"(^[A-Za-z]{1}:(?:\\|/))") 82 | if re_win_drive.match(pth) is not None or pth.startswith("//"): 83 | absolute = True 84 | elif pth.startswith('/'): 85 | absolute = True 86 | return absolute 87 | 88 | def resolve_meta_path(self, target): 89 | """ 90 | Resolve the path returned in the meta data. 91 | 92 | 1. See if path is defined as absolute and if so see 93 | if it exists 94 | 2. If relative, use the file's current directory 95 | (if available) as the base and see if the file 96 | can be found 97 | 3. If relative, and the file's current directory 98 | as the base proved fruitless, use the defined 99 | basepath (if available) 100 | """ 101 | basepath = self._overrides["builtin"].get("basepath") 102 | current_dir = None if self.file_name is None else os.path.dirname(self.file_name) 103 | if target is not None: 104 | target = os.path.expanduser(target) 105 | if not self.is_abs(target): 106 | for base in (current_dir, basepath): 107 | if base is not None: 108 | temp = os.path.join(base, target) 109 | if os.path.exists(temp): 110 | target = temp 111 | break 112 | elif not os.path.exists(target): 113 | target = None 114 | return target 115 | 116 | def get_base_path(self, basepath): 117 | """Get the base path to use when resolving basepath paths if possible.""" 118 | if basepath is not None: 119 | basepath = os.path.expanduser(basepath) 120 | 121 | if ( 122 | basepath is not None and os.path.exists(basepath) and 123 | self.is_abs(basepath) and os.path.isdir(basepath) 124 | ): 125 | # A valid path was fed in 126 | path = basepath 127 | basepath = path 128 | elif self.file_name is not None and os.path.exists(self.file_name): 129 | basepath = os.path.dirname(self.file_name) 130 | else: 131 | # Okay, there is no way to tell the orign. 132 | # We are probably a stream that has no specified 133 | # physical location. 134 | basepath = None 135 | 136 | return basepath 137 | 138 | def add_meta(self, meta): 139 | """Add meta data.""" 140 | meta = dict(list(meta.items()) + list(self._overrides.get("meta", {}).items())) 141 | self._overrides["meta"] = meta 142 | 143 | def apply_frontmatter(self, frontmatter): 144 | """Apply the provided frontmatter to override.""" 145 | # Handle basepath first 146 | 147 | if "basepath" in frontmatter: 148 | value = frontmatter["basepath"] 149 | self._overrides["builtin"]["basepath"] = self.get_base_path(value) 150 | del frontmatter["basepath"] 151 | 152 | for key, value in frontmatter.items(): 153 | if key == "settings" and isinstance(value, dict): 154 | for subkey, subvalue in value.items(): 155 | self._overrides[subkey] = subvalue 156 | elif key in BUILTIN_KEYS: 157 | if key == "references": 158 | if not isinstance(value, list): 159 | value = [value] 160 | refs = [] 161 | for ref in value: 162 | file_name = self.resolve_meta_path(ref) 163 | if file_name is not None and not os.path.isdir(file_name): 164 | refs.append(os.path.normpath(file_name)) 165 | self._overrides["builtin"][key] = refs 166 | if key == "destination": 167 | if value is not None: 168 | file_name = value 169 | if file_name is not None: 170 | directory = os.path.dirname(file_name) 171 | directory = self.resolve_meta_path(directory) 172 | else: 173 | directory = None 174 | if directory is not None: 175 | file_name = os.path.join(directory, os.path.basename(file_name)) 176 | if ( 177 | file_name is not None and 178 | (not os.path.exists(file_name) or not os.path.isdir(file_name)) 179 | ): 180 | self._overrides["builtin"][key] = file_name 181 | else: 182 | if isinstance(value, list): 183 | value = [str(v) for v in value] 184 | else: 185 | value = str(value) 186 | self._overrides["meta"][str(key)] = value 187 | -------------------------------------------------------------------------------- /markdown_wrapper.py: -------------------------------------------------------------------------------- 1 | """Markdown Preview wrapper.""" 2 | from __future__ import absolute_import 3 | import traceback 4 | from markdown import Markdown, util 5 | from markdown.extensions import Extension 6 | 7 | 8 | class StMarkdown(Markdown): 9 | """A wrapper around "markdown" lib.""" 10 | 11 | def __init__(self, *args, **kwargs): 12 | """Intialize.""" 13 | Markdown.__init__(self, *args, **kwargs) 14 | self.Meta = {} 15 | 16 | def registerExtensions(self, extensions, configs): # noqa 17 | """ 18 | Register extensions with this instance of Markdown. 19 | 20 | Keyword arguments: 21 | 22 | * extensions: A list of extensions, which can either 23 | be strings or objects. See the docstring on Markdown. 24 | * configs: A dictionary mapping module names to config options. 25 | 26 | We are overriding this in order to gracefully handle bad extensions 27 | and to prevent old deprecated style of 'extensions(option=value)'. 28 | """ 29 | for ext in extensions: 30 | try: 31 | # Make sure we aren't using old form `extension(option=value)` 32 | if isinstance(ext, util.string_type) and ('(' not in ext): 33 | ext = self.build_extension(ext, configs.get(ext, [])) 34 | if isinstance(ext, Extension): 35 | ext.extendMarkdown(self, globals()) 36 | elif ext is not None: 37 | raise TypeError( 38 | 'Extension "%s.%s" must be of type: "markdown.Extension"' 39 | % (ext.__class__.__module__, ext.__class__.__name__)) 40 | except Exception: 41 | print(str(traceback.format_exc())) 42 | 43 | return self 44 | -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "install": "README.md", 3 | "1.0.2": "CHANGES.md", 4 | "1.3.0": "CHANGES.md", 5 | "1.4.0": "CHANGES.md", 6 | "2.0.0": "CHANGES.md" 7 | } 8 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Markdown Preview Documentation 2 | site_url: https://revolunet.github.io/sublimetext-markdown-preview 3 | repo_url: https://github.com/revolunet/sublimetext-markdown-preview 4 | edit_uri: tree/master/docs/src/markdown 5 | site_description: Markdown preview and build plugin for Sublime Text 3 6 | copyright: | 7 |
emoji provided free by EmojiOne 8 | 9 | docs_dir: docs/src/markdown 10 | theme: 11 | name: material 12 | custom_dir: docs/theme 13 | palette: 14 | primary: blue 15 | accent: blue 16 | logo: 17 | icon: description 18 | font: 19 | text: Roboto 20 | code: Roboto Mono 21 | 22 | pages: 23 | - Markdown Preview: index.md 24 | - Installation: install.md 25 | - Usage: usage.md 26 | - Extras: extras.md 27 | - Changes: changes.md 28 | - License: license.md 29 | 30 | markdown_extensions: 31 | - markdown.extensions.toc: 32 | slugify: !!python/name:pymdownx.slugs.uslugify 33 | permalink: "\ue157" 34 | - markdown.extensions.admonition: 35 | - markdown.extensions.smarty: 36 | smart_quotes: false 37 | - pymdownx.betterem: 38 | - markdown.extensions.attr_list: 39 | - markdown.extensions.def_list: 40 | - markdown.extensions.tables: 41 | - markdown.extensions.abbr: 42 | - markdown.extensions.footnotes: 43 | - pymdownx.extrarawhtml: 44 | - pymdownx.superfences: 45 | - pymdownx.highlight: 46 | css_class: codehilite 47 | extend_pygments_lang: 48 | - name: php-inline 49 | lang: php 50 | options: 51 | startinline: true 52 | - name: pycon3 53 | lang: pycon 54 | options: 55 | python3: true 56 | - pymdownx.inlinehilite: 57 | - pymdownx.magiclink: 58 | repo_url_shortener: true 59 | repo_url_shorthand: true 60 | social_url_shorthand: true 61 | user: revolunet 62 | repo: sublimetext-markdown-preview 63 | - pymdownx.tilde: 64 | - pymdownx.caret: 65 | - pymdownx.smartsymbols: 66 | - pymdownx.emoji: 67 | emoji_generator: !!python/name:pymdownx.emoji.to_png 68 | - pymdownx.escapeall: 69 | hardbreak: True 70 | nbsp: True 71 | - pymdownx.tasklist: 72 | custom_checkbox: true 73 | - pymdownx.arithmatex: 74 | - pymdownx.mark: 75 | - pymdownx.striphtml: 76 | - pymdownx.snippets: 77 | base_path: docs/src/markdown/_snippets 78 | - pymdownx.keys: 79 | separator: "\uff0b" 80 | - pymdownx.details: 81 | 82 | extra: 83 | social: 84 | - type: github 85 | link: https://github.com/revolunet 86 | extra_css: 87 | - extra-d04c85ed4a.css 88 | extra_javascript: 89 | - extra-d8800ea088.js 90 | -------------------------------------------------------------------------------- /samples/customized-template-sample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ HEAD }} 5 | 6 | 7 | 42 | 43 | 44 |
45 | {{ BODY }} 46 |
47 |
48 |

49 | Markdown Preview Theme designed by @hozaka. 50 |

51 |
52 | 53 | 54 | 55 | 60 | -------------------------------------------------------------------------------- /samples/sample.md: -------------------------------------------------------------------------------- 1 | Sample Markdown Cheat Sheet 2 | =========================== 3 | 4 | This is a sample markdown file to help you write Markdown quickly :) 5 | 6 | If you use the fabulous [Sublime Text 2/3 editor][ST] along with the [Markdown Preview plugin][MarkdownPreview], open your ST2 Palette with `CMD+⇧+P` then choose `Markdown Preview in browser` to see the result in your browser. 7 | 8 | ## Text basics 9 | this is *italic* and this is **bold** . another _italic_ and another __bold__ 10 | 11 | this is `important` text. and percentage signs : % and `%` 12 | 13 | This is a paragraph with a footnote (builtin parser only). [^note-id] 14 | 15 | Insert `[ TOC ]` without spaces to generate a table of contents (builtin parsers only). 16 | 17 | ## Indentation 18 | > Here is some indented text 19 | >> even more indented 20 | 21 | ## Titles 22 | # Big title (h1) 23 | ## Middle title (h2) 24 | ### Smaller title (h3) 25 | #### and so on (hX) 26 | ##### and so on (hX) 27 | ###### and so on (hX) 28 | 29 | ## Example lists (1) 30 | 31 | - bullets can be `-`, `+`, or `*` 32 | - bullet list 1 33 | - bullet list 2 34 | - sub item 1 35 | - sub item 2 36 | 37 | with indented text inside 38 | 39 | - bullet list 3 40 | + bullet list 4 41 | * bullet list 5 42 | 43 | ## Links 44 | 45 | This is an [example inline link](http://lmgtfy.com/) and [another one with a title](http://lmgtfy.com/ "Hello, world"). 46 | 47 | Links can also be reference based : [reference 1][ref1] or [reference 2 with title][ref2]. 48 | 49 | References are usually placed at the bottom of the document 50 | 51 | ## Images 52 | 53 | A sample image : 54 | 55 | ![revolunet logo](http://www.revolunet.com/static/parisjs8/img/logo-revolunet-carre.jpg "revolunet logo") 56 | 57 | As links, images can also use references instead of inline links : 58 | 59 | ![revolunet logo][revolunet-logo] 60 | 61 | 62 | ## Code 63 | 64 | It's quite easy to show code in markdown files. 65 | 66 | Backticks can be used to `highlight` some words. 67 | 68 | Also, any indented block is considered a code block. If `enable_highlight` is `true`, syntax highlighting will be included (for the builtin parser - the github parser does this automatically). 69 | 70 | 73 | 74 | ## Math 75 | 76 | When `enable_mathjax` is `true`, inline math can be included \\(\frac{\pi}{2}\\) $\pi$ 77 | 78 | Alternatively, math can be written on its own line: 79 | 80 | $$F(\omega) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{\infty} f(t) \, e^{ - i \omega t}dt$$ 81 | 82 | \\[\int_0^1 f(t) \mathrm{d}t\\] 83 | 84 | \\[\sum_j \gamma_j^2/d_j\\] 85 | 86 | 87 | 88 | ## GitHub Flavored Markdown 89 | 90 | If you use the Github parser, you can use some of [Github Flavored Markdown][gfm] syntax : 91 | 92 | * User/Project@SHA: revolunet/sublimetext-markdown-preview@7da61badeda468b5019869d11000307e07e07401 93 | * User/Project#Issue: revolunet/sublimetext-markdown-preview#1 94 | * User : @revolunet 95 | 96 | Some Python code : 97 | 98 | ```python 99 | import random 100 | 101 | class CardGame(object): 102 | """ a sample python class """ 103 | NB_CARDS = 32 104 | def __init__(self, cards=5): 105 | self.cards = random.sample(range(self.NB_CARDS), 5) 106 | print 'ready to play' 107 | ``` 108 | 109 | Some Javascript code : 110 | 111 | ```js 112 | var config = { 113 | duration: 5, 114 | comment: 'WTF' 115 | } 116 | // callbacks beauty un action 117 | async_call('/path/to/api', function(json) { 118 | another_call(json, function(result2) { 119 | another_another_call(result2, function(result3) { 120 | another_another_another_call(result3, function(result4) { 121 | alert('And if all went well, i got my result :)'); 122 | }); 123 | }); 124 | }); 125 | }) 126 | ``` 127 | 128 | The Github Markdown also brings some [nice Emoji support][emoji] : :+1: :heart: :beer: 129 | 130 | [^note-id]: This is the text of the note. 131 | 132 | ## Parsers and Extensions 133 | 134 | Markdown Preview comes with **Python-Markdown** preloaded. 135 | 136 | ### *Python-Markdown* 137 | 138 | The [Python-Markdown Parser][] provides support for several extensions. 139 | 140 | [Python-Markdown Parser]: https://github.com/Python-Markdown/markdown 141 | 142 | #### Extra Extensions 143 | 144 | * `abbr` -- [Abbreviations][] 145 | * `attr_list` -- [Attribute Lists][] 146 | * `def_list` -- [Definition Lists][] 147 | * `fenced_code` -- [Fenced Code Blocks][] 148 | * `footnotes` -- [Footnotes][] 149 | * `tables` -- [Tables][] 150 | * `smart_strong` -- [Smart Strong][] 151 | 152 | [Abbreviations]: https://python-markdown.github.io/extensions/abbreviations 153 | [Attribute Lists]: https://python-markdown.github.io/extensions/attr_list 154 | [Definition Lists]: https://python-markdown.github.io/extensions/definition_lists 155 | [Fenced Code Blocks]: https://python-markdown.github.io/extensions/fenced_code_blocks 156 | [Footnotes]: https://python-markdown.github.io/extensions/footnotes 157 | [Tables]: https://python-markdown.github.io/extensions/tables 158 | [Smart Strong]: https://python-markdown.github.io/extensions/smart_strong 159 | 160 | 161 | You can enable them all at once using the `extra` keyword. 162 | 163 | extensions: [ 'extra' ] 164 | 165 | If you want all the extras plus the `toc` extension, 166 | your settings would look like this: 167 | 168 | { 169 | ... 170 | parser: 'markdown', 171 | extensions: ['extra', 'toc'], 172 | ... 173 | } 174 | 175 | 176 | #### Other Extensions 177 | 178 | There are also some extensions that are not included in Markdown Extra 179 | but come in the standard Python-Markdown library. 180 | 181 | * `code-hilite` -- [CodeHilite][] 182 | * `header-id` -- [HeaderId][] 183 | * `meta_data` -- [Meta-Data][] 184 | * `nl2br` -- [New Line to Break][] 185 | * `sane_lists` -- [Sane Lists][] 186 | * `smarty` -- [Smarty][] 187 | * `toc` -- [Table of Contents][] 188 | * `wikilinks` -- [WikiLinks][] 189 | 190 | [CodeHilite]: https://python-markdown.github.io/extensions/code_hilite 191 | [HeaderId]: https://python-markdown.github.io/extensions/header_id 192 | [Meta-Data]: https://python-markdown.github.io/extensions/meta_data 193 | [New Line to Break]: https://python-markdown.github.io/extensions/nl2br 194 | [Sane Lists]: https://python-markdown.github.io/extensions/sane_lists 195 | [Table of Contents]: https://python-markdown.github.io/extensions/toc 196 | [WikiLinks]: https://python-markdown.github.io/extensions/wikilinks 197 | [Smarty]: hhttps://python-markdown.github.io/extensions/smarty 198 | 199 | #### 3rd Party Extensions 200 | 201 | *Python-Markdown* is designed to be extended. 202 | 203 | Some included ones are: 204 | 205 | * `delete` -- github style delte support via `~~word~~` 206 | * `githubemoji` -- github emoji support 207 | * `tasklist` -- github style tasklists 208 | * `magiclink` -- github style auto link conversion of http|ftp links 209 | * `headeranchor` -- github style header anchor links 210 | * `github` -- Adds the above extensions in one shot 211 | * `b64` -- convert and embed local images to base64. Setup by adding this `b64(base_path=${BASE_PATH})` 212 | 213 | There are also a number of others available: 214 | 215 | Just fork this repo and add your extensions inside the `.../Packages/Markdown Preview/markdown/extensions/` folder. 216 | 217 | Check out the list of [3rd Party extensions]( 218 | https://github.com/waylan/Python-Markdown/wiki/Third-Party-Extensions). 219 | 220 | 221 | #### Default Extensions 222 | 223 | The default extensions are: 224 | 225 | * `footnotes` -- [Footnotes] 226 | * `toc` -- [Table of Contents] 227 | * `fenced_code` -- [Fenced Code Blocks] 228 | * `tables` -- [Tables] 229 | 230 | Use the `default` keyword, to select them all. 231 | If you want all the defaults plus the `definition_lists` extension, 232 | your settings would look like this: 233 | 234 | { 235 | ... 236 | parser: 'markdown', 237 | extensions: ['default', 'definition_lists'], 238 | ... 239 | } 240 | 241 | ## Examples 242 | 243 | ### Tables 244 | 245 | The `tables` extension of the *Python-Markdown* parser is activated by default, 246 | but is currently **not** available in *Markdown2*. 247 | 248 | The syntax was adopted from the [php markdown project](http://michelf.ca/projects/php-markdown/extra/#table), 249 | and is also used in github flavoured markdown. 250 | 251 | | Year | Temperature (low) | Temperature (high) | 252 | | ---- | ----------------- | -------------------| 253 | | 1900 | -10 | 25 | 254 | | 1910 | -15 | 30 | 255 | | 1920 | -10 | 32 | 256 | 257 | 258 | ### Wiki Tables 259 | 260 | If you are using *Markdown2* with the `wiki-tables` extra activated you should see a table below: 261 | 262 | || *Year* || *Temperature (low)* || *Temperature (high)* || 263 | || 1900 || -10 || 25 || 264 | || 1910 || -15 || 30 || 265 | || 1920 || -10 || 32 || 266 | 267 | 268 | ### Definition Lists 269 | 270 | This example requires *Python Markdown*'s `def_list` extension. 271 | 272 | Apple 273 | : Pomaceous fruit of plants of the genus Malus in 274 | the family Rosaceae. 275 | 276 | Orange 277 | : The fruit of an evergreen tree of the genus Citrus. 278 | 279 | 280 | ## About 281 | 282 | This plugin and this sample file is proudly brought to you by the [revolunet team][revolunet] 283 | 284 | [ref1]: http://revolunet.com 285 | [ref2]: http://revolunet.com "rich web apps" 286 | [MarkdownREF]: http://daringfireball.net/projects/markdown/basics 287 | [MarkdownPreview]: https://github.com/revolunet/sublimetext-markdown-preview 288 | [ST]: http://sublimetext.com 289 | [revolunet]: http://revolunet.com 290 | [revolunet-logo]: http://www.revolunet.com/static/parisjs8/img/logo-revolunet-carre.jpg "revolunet logo" 291 | [gfm]: https://help.github.com/articles/github-flavored-markdown/ 292 | [emoji]: http://www.emoji-cheat-sheet.com/ 293 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore=D202,D203,D401 3 | max-line-length=120 4 | exclude=lib/*,desktop/* 5 | -------------------------------------------------------------------------------- /tests/abbreviations.md: -------------------------------------------------------------------------------- 1 | *[HTML]: Hyper Text Markup Language 2 | *[W3C]: World Wide Web Consortium 3 | -------------------------------------------------------------------------------- /tests/footnotes.md: -------------------------------------------------------------------------------- 1 | [^1]: This is a footnote 2 | [^label]: A footnote on "label" 3 | [^!DEF]: The footnote for definition 4 | -------------------------------------------------------------------------------- /tests/logo-revolunet-carre.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/revolunet/sublimetext-markdown-preview/154bdd63f27970dd4c775c5c57810d7f18c64ea5/tests/logo-revolunet-carre.jpg -------------------------------------------------------------------------------- /tests/references.md: -------------------------------------------------------------------------------- 1 | [1]: https://github.com/revolunet/sublimetext-markdown-preview 2 | -------------------------------------------------------------------------------- /tests/test.md: -------------------------------------------------------------------------------- 1 | --- 2 | # Builtin values 3 | references: 4 | - references.md 5 | - abbreviations.md 6 | - footnotes.md 7 | 8 | destination: destination.html 9 | 10 | # Meta Data 11 | title: Test Page 12 | author: 13 | - John Doe 14 | - Jane Doe 15 | 16 | # Settings overrides 17 | settings: 18 | pygments_style: github 19 | js: 20 | - https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.7/raphael.min.js 21 | - https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js 22 | - https://cdnjs.cloudflare.com/ajax/libs/js-sequence-diagrams/1.0.6/sequence-diagram-min.js 23 | - https://cdnjs.cloudflare.com/ajax/libs/flowchart/1.6.5/flowchart.min.js 24 | - res://Markdown Preview/js/uml.js 25 | - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js 26 | - res://Markdown Preview/js/math_config.js 27 | markdown_extensions: 28 | - markdown.extensions.footnotes 29 | - markdown.extensions.attr_list 30 | - markdown.extensions.def_list 31 | - markdown.extensions.tables 32 | - markdown.extensions.abbr 33 | - markdown.extensions.toc: 34 | permalink: "\ue157" 35 | - markdown.extensions.smarty 36 | - markdown.extensions.meta 37 | - markdown.extensions.admonition 38 | - markdown.extensions.codehilite: 39 | guess_lang: false 40 | - pymdownx.arithmatex: 41 | generic: true 42 | - pymdownx.extrarawhtml 43 | - pymdownx.progressbar 44 | - pymdownx.caret: 45 | superscript: false 46 | - pymdownx.magiclink: 47 | repo_url_shortener: true 48 | repo_url_shorthand: true 49 | user: revolunet 50 | repo: sublimetext-markdown-preview 51 | - pymdownx.betterem 52 | - pymdownx.tilde: 53 | subscript: false 54 | - pymdownx.emoji: 55 | emoji_index: !!python/name:pymdownx.emoji.gemoji 56 | emoji_generator: !!python/name:pymdownx.emoji.to_png 57 | alt: short 58 | options: 59 | attributes: 60 | align: absmiddle 61 | height: 20px 62 | width: 20px 63 | image_path: https://assets-cdn.github.com/images/icons/emoji/unicode/ 64 | non_standard_image_path: https://assets-cdn.github.com/images/icons/emoji/ 65 | - pymdownx.tasklist 66 | - pymdownx.superfences 67 | --- 68 | test: This tests the meta extension 69 | title: This title will be overridden by YAML 70 | 71 | # Cheat Sheet and Test 72 | 73 | [TOC] 74 | 75 | ## Headers 76 | 77 | ``` 78 | # H1 79 | ## H2 80 | ### H3 81 | #### H4 82 | ##### H5 83 | ###### H6 84 | ### Duplicate Header 85 | ### Duplicate Header 86 | ``` 87 | 88 | # H1 89 | ## H2 90 | ### H3 91 | #### H4 92 | ##### H5 93 | ###### H6 94 | ### Duplicate Header 95 | ### Duplicate Header 96 | 97 | ## Paragraphs 98 | 99 | ``` 100 | This is a paragraph. 101 | I am still part of the paragraph. 102 | 103 | New paragraph. 104 | ``` 105 | 106 | This is a paragraph. 107 | I am still part of the paragraph. 108 | 109 | New paragraph. 110 | 111 | ## Inline 112 | 113 | ``` 114 | `inline block` 115 | 116 | ctrl+alt+del 117 | 118 | **bold 1** and __bold 2__ 119 | 120 | *italic 1* and _italic 2_ 121 | 122 | ~~strike~~ 123 | 124 | 125 | ***bold 1 and italic 1*** 126 | 127 | ___bold 2 and italic 2___ 128 | 129 | __*bold 2 and italic 1*__ 130 | 131 | **_bold 1 and italic 2_** 132 | 133 | 134 | ~~*strike italic 1*~~ and *~~strike italic 2~~* 135 | 136 | ~~_strike italic 2_~~ and _~~strike italic 2~~_ 137 | 138 | 139 | ~~**strike bold 1**~~ and **~~strike bold 1~~** 140 | 141 | ~~__strike bold 2__~~ and __~~strike bold 2~~__ 142 | 143 | 144 | ~~***strike italic 1 bold 1***~~ and ***~~strike italic 1 bold 1~~*** 145 | 146 | ~~___strike italic 2 bold 2___~~ and ___~~strike italic 2 bold 2~~___ 147 | 148 | **~~*strike italic 1 bold 1*~~** and *~~**strike italic 1 bold 1**~~* 149 | 150 | __~~_strike italic 2 bold 2_~~__ and _~~__strike italic 2 bold 2__~~_ 151 | 152 | **~~_strike italic 2 bold 1_~~** and _~~**strike italic 2 bold 1**~~_ 153 | 154 | __~~*strike italic 1 bold 2*~~__ and *~~__strike italic 1 bold 2__~~* 155 | 156 | ``` 157 | 158 | `inline block` 159 | 160 | ctrl+alt+del 161 | 162 | **bold 1** and __bold 2__ 163 | 164 | *italic 1* and _italic 2_ 165 | 166 | ~~strike~~ 167 | 168 | 169 | ***bold 1 and italic 1*** 170 | 171 | ___bold 2 and italic 2___ 172 | 173 | __*bold 2 and italic 1*__ 174 | 175 | **_bold 1 and italic 2_** 176 | 177 | 178 | ~~*strike italic 1*~~ and *~~strike italic 2~~* 179 | 180 | ~~_strike italic 2_~~ and _~~strike italic 2~~_ 181 | 182 | 183 | ~~**strike bold 1**~~ and **~~strike bold 1~~** 184 | 185 | ~~__strike bold 2__~~ and __~~strike bold 2~~__ 186 | 187 | 188 | ~~***strike italic 1 bold 1***~~ and ***~~strike italic 1 bold 1~~*** 189 | 190 | ~~___strike italic 2 bold 2___~~ and ___~~strike italic 2 bold 2~~___ 191 | 192 | **~~*strike italic 1 bold 1*~~** and *~~**strike italic 1 bold 1**~~* 193 | 194 | __~~_strike italic 2 bold 2_~~__ and _~~__strike italic 2 bold 2__~~_ 195 | 196 | **~~_strike italic 2 bold 1_~~** and _~~**strike italic 2 bold 1**~~_ 197 | 198 | __~~*strike italic 1 bold 2*~~__ and *~~__strike italic 1 bold 2__~~* 199 | 200 | 201 | ## Links 202 | 203 | Footnote, reference sources are provided in separate markdowns files specified in frontmatter. 204 | ``` 205 | [Reference Link][1] 206 | 207 | Footnotes[^1] have a label[^label] and a definition[^!DEF] 208 | 209 | Web image 210 | ![Web Picture](http://www.revolunet.com/static/parisjs8/img/logo-revolunet-carre.jpg "Web Picture") 211 | 212 | Local image 213 | ![Local Picture](logo-revolunet-carre.jpg "Local Picture") 214 | 215 | contact@revolunet.com 216 | 217 | @revolunet 218 | 219 | Issue #1 220 | 221 | https://github.com/revolunet/sublimetext-markdown-preview/ 222 | 223 | This is a link https://github.com/revolunet/sublimetext-markdown-preview/. 224 | 225 | This is a link "https://github.com/revolunet/sublimetext-markdown-preview/". 226 | 227 | With this link (https://github.com/revolunet/sublimetext-markdown-preview/), it still works. 228 | 229 | [1]: https://github.com/revolunet/sublimetext-markdown-preview/ 230 | [^1]: This is a footnote 231 | [^label]: A footnote on "label" 232 | [^!DEF]: The footnote for definition 233 | ``` 234 | 235 | [Reference Link][1] 236 | 237 | Footnotes[^1] have a label[^label] and a definition[^!DEF] 238 | 239 | Web image 240 | ![Web Picture](http://www.revolunet.com/static/parisjs8/img/logo-revolunet-carre.jpg "Web Picture") 241 | 242 | Local image 243 | ![Local Picture](logo-revolunet-carre.jpg "Local Picture") 244 | 245 | www.google.com 246 | 247 | contact@revolunet.com 248 | 249 | @revolunet 250 | 251 | Issue #1 252 | 253 | https://github.com/revolunet/sublimetext-markdown-preview/ 254 | 255 | This is a link https://github.com/revolunet/sublimetext-markdown-preview/. 256 | 257 | This is a link "https://github.com/revolunet/sublimetext-markdown-preview/". 258 | 259 | With this link (https://github.com/revolunet/sublimetext-markdown-preview/), it still works. 260 | 261 | ## Abbreviation 262 | 263 | Abbreviations source are found in a separate markdown file specified in frontmatter. 264 | ``` 265 | The HTML specification 266 | is maintained by the W3C. 267 | 268 | *[HTML]: Hyper Text Markup Language 269 | *[W3C]: World Wide Web Consortium 270 | ``` 271 | 272 | The HTML specification 273 | is maintained by the W3C. 274 | 275 | ## Unordered List 276 | 277 | ``` 278 | Unordered List 279 | 280 | - item 1 281 | * item A 282 | * item B 283 | more text 284 | + item a 285 | + item b 286 | + item c 287 | * item C 288 | - item 2 289 | - item 3 290 | ``` 291 | 292 | Unordered List 293 | 294 | - item 1 295 | * item A 296 | * item B 297 | more text 298 | + item a 299 | + item b 300 | + item c 301 | * item C 302 | - item 2 303 | - item 3 304 | 305 | 306 | ## Ordered List 307 | 308 | ``` 309 | Ordered List 310 | 311 | 1. item 1 312 | 1. item A 313 | 2. item B 314 | more text 315 | 1. item a 316 | 2. item b 317 | 3. item c 318 | 3. item C 319 | 2. item 2 320 | 3. item 3 321 | ``` 322 | 323 | Ordered List 324 | 325 | 1. item 1 326 | 1. item A 327 | 2. item B 328 | more text 329 | 1. item a 330 | 2. item b 331 | 3. item c 332 | 3. item C 333 | 2. item 2 334 | 3. item 3 335 | 336 | ## Task List 337 | 338 | ``` 339 | Task List 340 | 341 | - [X] item 1 342 | * [X] item A 343 | * [ ] item B 344 | more text 345 | + [x] item a 346 | + [ ] item b 347 | + [x] item c 348 | * [X] item C 349 | - [ ] item 2 350 | - [ ] item 3 351 | ``` 352 | 353 | Task List 354 | 355 | - [X] item 1 356 | * [X] item A 357 | * [ ] item B 358 | more text 359 | + [x] item a 360 | + [ ] item b 361 | + [x] item c 362 | * [X] item C 363 | - [ ] item 2 364 | - [ ] item 3 365 | 366 | ## Mixed Lists 367 | 368 | `Really Mixed Lists` should break with `sane_lists` on. 369 | 370 | ``` 371 | Mixed Lists 372 | 373 | - item 1 374 | * [X] item A 375 | * [ ] item B 376 | more text 377 | 1. item a 378 | 2. itemb 379 | 3. item c 380 | * [X] item C 381 | - item 2 382 | - item 3 383 | 384 | 385 | Really Mixed Lists 386 | 387 | - item 1 388 | * [X] item A 389 | - item B 390 | more text 391 | 1. item a 392 | + itemb 393 | + [ ] item c 394 | 3. item C 395 | 2. item 2 396 | - [X] item 3 397 | ``` 398 | 399 | Mixed Lists 400 | 401 | - item 1 402 | * [X] item A 403 | * [ ] item B 404 | more text 405 | 1. item a 406 | 2. itemb 407 | 3. item c 408 | * [X] item C 409 | - item 2 410 | - item 3 411 | 412 | 413 | Really Mixed Lists 414 | 415 | - item 1 416 | * [X] item A 417 | - item B 418 | more text 419 | 1. item a 420 | + itemb 421 | + [ ] item c 422 | 3. item C 423 | 2. item 2 424 | - [X] item 3 425 | 426 | 427 | ## Dictionary 428 | 429 | ``` 430 | Dictionary 431 | : item 1 432 | 433 | item 2 434 | 435 | item 3 436 | ``` 437 | 438 | Dictionary 439 | : item 1 440 | 441 | item 2 442 | 443 | item 3 444 | 445 | ## Blocks 446 | 447 | ``` 448 | This is a block. 449 | 450 | This is more of a block. 451 | 452 | ``` 453 | 454 | This is a block. 455 | 456 | This is more of a block. 457 | 458 | 459 | ## Block Quotes 460 | 461 | ``` 462 | > This is a block quote 463 | >> How does it look? 464 | ``` 465 | 466 | > This is a block quote. 467 | >> How does it look? 468 | > I think it looks good. 469 | 470 | ## Fenced Block 471 | 472 | Assuming guessing is not enabled. 473 | 474 | ````` 475 | ``` 476 | // Fenced **without** highlighting 477 | function doIt() { 478 | for (var i = 1; i <= slen ; i^^) { 479 | setTimeout("document.z.textdisplay.value = newMake()", i*300); 480 | setTimeout("window.status = newMake()", i*300); 481 | } 482 | } 483 | ``` 484 | 485 | ```javascript 486 | // Fenced **with** highlighting 487 | function doIt() { 488 | for (var i = 1; i <= slen ; i^^) { 489 | setTimeout("document.z.textdisplay.value = newMake()", i*300); 490 | setTimeout("window.status = newMake()", i*300); 491 | } 492 | } 493 | ``` 494 | ````` 495 | 496 | ``` 497 | // Fenced **without** highlighting 498 | function doIt() { 499 | for (var i = 1; i <= slen ; i^^) { 500 | setTimeout("document.z.textdisplay.value = newMake()", i*300); 501 | setTimeout("window.status = newMake()", i*300); 502 | } 503 | } 504 | ``` 505 | 506 | ```javascript 507 | // Fenced **with** highlighting 508 | function doIt() { 509 | for (var i = 1; i <= slen ; i^^) { 510 | setTimeout("document.z.textdisplay.value = newMake()", i*300); 511 | setTimeout("window.status = newMake()", i*300); 512 | } 513 | } 514 | ``` 515 | 516 | ## Tables 517 | 518 | ``` 519 | | _Colors_ | Fruits | Vegetable | 520 | | ------------- |:---------------:| -----------------:| 521 | | Red | *Apple* | [Pepper](#Tables) | 522 | | ~~Orange~~ | Oranges | **Carrot** | 523 | | Green | ~~***Pears***~~ | Spinach | 524 | ``` 525 | 526 | | _Colors_ | Fruits | Vegetable | 527 | | ------------- |:---------------:| ------------:| 528 | | Red | *Apple* | Pepper | 529 | | ~~Orange~~ | Oranges | **Carrot** | 530 | | Green | ~~***Pears***~~ | Spinach | 531 | 532 | ## Smart Strong 533 | 534 | ``` 535 | Text with double__underscore__words. 536 | 537 | __Strong__ still works. 538 | 539 | __this__works__too__ 540 | ``` 541 | 542 | Text with double__underscore__words. 543 | 544 | __Strong__ still works. 545 | 546 | __this__works__too__ 547 | 548 | ## Smarty 549 | 550 | ``` 551 | "double quotes" 552 | 553 | 'single quotes' 554 | 555 | da--sh 556 | 557 | elipsis... 558 | ``` 559 | 560 | "double quotes" 561 | 562 | 'single quotes' 563 | 564 | da--sh 565 | 566 | elipsis... 567 | 568 | ## Attribute List 569 | 570 | ``` 571 | Normal Text 572 | 573 | Modified Text 574 | {: style="font-weight:bold;" } 575 | ``` 576 | 577 | Normal Text 578 | 579 | Modified Text 580 | {: style="font-weight:bold;" } 581 | 582 | ## Admonition 583 | 584 | ``` 585 | !!! Attention "Success!" 586 | You can use inline ~~stuff~~ markup too! 587 | 588 | !!! Hint "Info!" 589 | - Here is some info. 590 | - And some more 591 | 592 | !!! Caution "Warning!" 593 | - [X] Make sure you turn off the stove 594 | - [X] Don't run with scissors 595 | 596 | !!! Danger "Alert!" 597 | You really need to read [this](#admonition)! 598 | 599 | !!! Question "Question?" 600 | Are you serious? 601 | 602 | !!! Note "Note" 603 | :smile: 604 | 605 | > Not all markup can be placed in these boxes, but you can fit all sorts of things in them. But you will notice that the styles don't always play nice with each other. Additional CSS could fix this though. 606 | 607 | Stuff like _this_ works too. 608 | 609 | | _Colors_ | Fruits | Vegetable | 610 | | ------------- |:---------------:| ------------:| 611 | | Red | *Apple* | Pepper | 612 | | ~~Orange~~ | Oranges | **Carrot** | 613 | | Green | ~~***Pears***~~ | Spinach | 614 | 615 | !!! Unknown "Title" 616 | Default class style 617 | ``` 618 | 619 | !!! Attention "Success!" 620 | You can use inline ~~stuff~~ markup too! 621 | 622 | !!! Hint "Info!" 623 | - Here is some info. 624 | - And some more 625 | 626 | !!! Caution "Warning!" 627 | - [X] Make sure you turn off the stove 628 | - [X] Don't run with scissors 629 | 630 | !!! Danger "Alert!" 631 | You really need to read [this](#admonition)! 632 | 633 | !!! Question "Question?" 634 | Are you serious? 635 | 636 | !!! Note "Note" 637 | :smile: 638 | 639 | > Not all markup can be placed in these boxes, but you can fit all sorts of things in them. But you will notice that the styles don't always play nice with each other. Additional CSS could fix this though. 640 | 641 | Stuff like _this_ works too. 642 | 643 | | _Colors_ | Fruits | Vegetable | 644 | | ------------- |:---------------:| ------------:| 645 | | Red | *Apple* | Pepper | 646 | | ~~Orange~~ | Oranges | **Carrot** | 647 | | Green | ~~***Pears***~~ | Spinach | 648 | 649 | !!! Unknown "Title" 650 | Default class style 651 | 652 | ## Github Emoji 653 | 654 | ``` 655 | This is a test for emoji :smile:. The emojis are images linked to github assets :octocat:. 656 | ``` 657 | 658 | This is a test for emoji :smile:. The emojis are images linked to github assets :octocat:. 659 | 660 | ### People 661 | 662 | :+1::-1::alien::angel::anger::angry::anguished::astonished::baby::blue_heart::blush::boom::bow::bowtie::boy::bride_with_veil::broken_heart::bust_in_silhouette::busts_in_silhouette::clap::cold_sweat::collision::confounded::confused::construction_worker::cop::couple::couple_with_heart::couplekiss::cry::crying_cat_face::cupid::dancer::dancers::dash::disappointed::disappointed_relieved::dizzy::dizzy_face::droplet::ear::exclamation::expressionless::eyes::facepunch::family::fearful::feelsgood::feet::finnadie::fire::fist::flushed::frowning::fu::girl::goberserk::godmode::green_heart::grey_exclamation::grey_question::grimacing::grin::grinning::guardsman::haircut::hand::hankey::hear_no_evil::heart::heart_eyes::heart_eyes_cat::heartbeat::heartpulse::hurtrealbad::hushed::imp::information_desk_person::innocent::japanese_goblin::japanese_ogre::joy::joy_cat::kiss::kissing::kissing_cat::kissing_closed_eyes::kissing_heart::kissing_smiling_eyes::laughing::lips::love_letter::man::man_with_gua_pi_mao::man_with_turban::mask::massage::metal::muscle::musical_note::nail_care::neckbeard::neutral_face::no_good::no_mouth::nose::notes::ok_hand::ok_woman::older_man::older_woman::open_hands::open_mouth::pensive::persevere::person_frowning::person_with_blond_hair::person_with_pouting_face::point_down::point_left::point_right::point_up::point_up_2::poop::pouting_cat::pray::princess::punch::purple_heart::question::rage::rage1::rage2::rage3::rage4::raised_hand::raised_hands::raising_hand::relaxed::relieved::revolving_hearts::runner::running::satisfied::scream::scream_cat::see_no_evil::shit::skull::sleeping::sleepy::smile::smile_cat::smiley::smiley_cat::smiling_imp::smirk::smirk_cat::sob::sparkles::sparkling_heart::speak_no_evil::speech_balloon::star::star2::stuck_out_tongue::stuck_out_tongue_closed_eyes::stuck_out_tongue_winking_eye::sunglasses::suspect::sweat::sweat_drops::sweat_smile::thought_balloon::thumbsdown::thumbsup::tired_face::tongue::triumph::trollface::two_hearts::two_men_holding_hands::two_women_holding_hands::unamused::v::walking::wave::weary::wink::woman::worried::yellow_heart::yum::zzz: 663 | 664 | ### Nature 665 | 666 | :ant::baby_chick::bear::bee::beetle::bird::blossom::blowfish::boar::bouquet::bug::cactus::camel::cat::cat2::cherry_blossom::chestnut::chicken::cloud::cow::cow2::crescent_moon::crocodile::cyclone::deciduous_tree::dog::dog2::dolphin::dragon::dragon_face::dromedary_camel::ear_of_rice::earth_africa::earth_americas::earth_asia::elephant::evergreen_tree::fallen_leaf::first_quarter_moon::first_quarter_moon_with_face::fish::foggy::four_leaf_clover::frog::full_moon::full_moon_with_face::globe_with_meridians::goat::hamster::hatched_chick::hatching_chick::herb::hibiscus::honeybee::horse::koala::last_quarter_moon::last_quarter_moon_with_face::leaves::leopard::maple_leaf::milky_way::monkey::monkey_face::moon::mouse::mouse2::mushroom::new_moon::new_moon_with_face::night_with_stars::ocean::octocat::octopus::ox::palm_tree::panda_face::partly_sunny::paw_prints::penguin::pig::pig2::pig_nose::poodle::rabbit::rabbit2::racehorse::ram::rat::rooster::rose::seedling::sheep::shell::snail::snake::snowflake::snowman::squirrel::sun_with_face::sunflower::sunny::tiger::tiger2::tropical_fish::tulip::turtle::umbrella::volcano::waning_crescent_moon::waning_gibbous_moon::water_buffalo::waxing_crescent_moon::waxing_gibbous_moon::whale::whale2::wolf::zap: 667 | 668 | ### Objects 669 | 670 | :8ball::alarm_clock::apple::art::athletic_shoe::baby_bottle::balloon::bamboo::banana::bar_chart::baseball::basketball::bath::bathtub::battery::beer::beers::bell::bento::bicyclist::bikini::birthday::black_joker::black_nib::blue_book::bomb::book::bookmark::bookmark_tabs::books::boot::bowling::bread::briefcase::bulb::cake::calendar::calling::camera::candy::card_index::cd::chart_with_downwards_trend::chart_with_upwards_trend::cherries::chocolate_bar::christmas_tree::clapper::clipboard::closed_book::closed_lock_with_key::closed_umbrella::clubs::cocktail::coffee::computer::confetti_ball::cookie::corn::credit_card::crown::crystal_ball::curry::custard::dango::dart::date::diamonds::dollar::dolls::door::doughnut::dress::dvd::e-mail::egg::eggplant::electric_plug::email::envelope::envelope_with_arrow::euro::eyeglasses::fax::file_folder::fireworks::fish_cake::fishing_pole_and_fish::flags::flashlight::flipper::floppy_disk::flower_playing_cards::football::footprints::fork_and_knife::fried_shrimp::fries::game_die::gem::ghost::gift::gift_heart::golf::grapes::green_apple::green_book::guitar::gun::hamburger::hammer::handbag::headphones::hearts::high_brightness::high_heel::hocho::honey_pot::horse_racing::hourglass::hourglass_flowing_sand::ice_cream::icecream::inbox_tray::incoming_envelope::iphone::jack_o_lantern::jeans::key::kimono::lantern::ledger::lemon::lipstick::lock::lock_with_ink_pen::lollipop::loop::loud_sound::loudspeaker::low_brightness::mag::mag_right::mahjong::mailbox::mailbox_closed::mailbox_with_mail::mailbox_with_no_mail::mans_shoe::meat_on_bone::mega::melon::memo::microphone::microscope::minidisc::money_with_wings::moneybag::mortar_board::mountain_bicyclist::movie_camera::musical_keyboard::musical_score::mute::name_badge::necktie::newspaper::no_bell::notebook::notebook_with_decorative_cover::nut_and_bolt::oden::open_book::open_file_folder::orange_book::outbox_tray::package::page_facing_up::page_with_curl::pager::paperclip::peach::pear::pencil::pencil2::phone::pill::pineapple::pizza::postal_horn::postbox::pouch::poultry_leg::pound::purse::pushpin::radio::ramen::ribbon::rice::rice_ball::rice_cracker::rice_scene::ring::rugby_football::running_shirt_with_sash::sake::sandal::santa::satellite::saxophone::school_satchel::scissors::scroll::seat::shaved_ice::shirt::shoe::shower::ski::smoking::snowboarder::soccer::sound::space_invader::spades::spaghetti::sparkle::sparkler::speaker::stew::straight_ruler::strawberry::surfer::sushi::sweet_potato::swimmer::syringe::tada::tanabata_tree::tangerine::tea::telephone::telephone_receiver::telescope::tennis::toilet::tomato::tophat::triangular_ruler::trophy::tropical_drink::trumpet::tshirt::tv::unlock::vhs::video_camera::video_game::violin::watch::watermelon::wind_chime::wine_glass::womans_clothes::womans_hat::wrench::yen: 671 | 672 | ### Places 673 | 674 | :aerial_tramway::airplane::ambulance::anchor::articulated_lorry::atm::bank::barber::beginner::bike::blue_car::boat::bridge_at_night::bullettrain_front::bullettrain_side::bus::busstop::car::carousel_horse::checkered_flag::church::circus_tent::city_sunrise::city_sunset::cn::construction::convenience_store::crossed_flags::de::department_store::es::european_castle::european_post_office::factory::ferris_wheel::fire_engine::fountain::fr::fuelpump::gb::helicopter::hospital::hotel::hotsprings::house::house_with_garden::it::izakaya_lantern::japan::japanese_castle::jp::kr::light_rail::love_hotel::minibus::monorail::mount_fuji::mountain_cableway::mountain_railway::moyai::office::oncoming_automobile::oncoming_bus::oncoming_police_car::oncoming_taxi::performing_arts::police_car::post_office::railway_car::rainbow::red_car::rocket::roller_coaster::rotating_light::round_pushpin::rowboat::ru::sailboat::school::ship::slot_machine::speedboat::stars::station::statue_of_liberty::steam_locomotive::sunrise::sunrise_over_mountains::suspension_railway::taxi::tent::ticket::tokyo_tower::tractor::traffic_light::train::train2::tram::triangular_flag_on_post::trolleybus::truck::uk::us::vertical_traffic_light::warning::wedding: 675 | 676 | ### Symbols 677 | 678 | :100::1234::a::ab::abc::abcd::accept::aquarius::aries::arrow_backward::arrow_double_down::arrow_double_up::arrow_down::arrow_down_small::arrow_forward::arrow_heading_down::arrow_heading_up::arrow_left::arrow_lower_left::arrow_lower_right::arrow_right::arrow_right_hook::arrow_up::arrow_up_down::arrow_up_small::arrow_upper_left::arrow_upper_right::arrows_clockwise::arrows_counterclockwise::b::baby_symbol::back::baggage_claim::ballot_box_with_check::bangbang::black_circle::black_large_square::black_medium_small_square::black_medium_square::black_small_square::black_square_button::cancer::capital_abcd::capricorn::chart::children_crossing::cinema::cl::clock1::clock10::clock1030::clock11::clock1130::clock12::clock1230::clock130::clock2::clock230::clock3::clock330::clock4::clock430::clock5::clock530::clock6::clock630::clock7::clock730::clock8::clock830::clock9::clock930::congratulations::cool::copyright::curly_loop::currency_exchange::customs::diamond_shape_with_a_dot_inside::do_not_litter::eight::eight_pointed_black_star::eight_spoked_asterisk::end::fast_forward::five::four::free::gemini::hash::heart_decoration::heavy_check_mark::heavy_division_sign::heavy_dollar_sign::heavy_exclamation_mark::heavy_minus_sign::heavy_multiplication_x::heavy_plus_sign::id::ideograph_advantage::information_source::interrobang::keycap_ten::koko::large_blue_circle::large_blue_diamond::large_orange_diamond::left_luggage::left_right_arrow::leftwards_arrow_with_hook::leo::libra::link::m::mens::metro::mobile_phone_off::negative_squared_cross_mark::new::ng::nine::no_bicycles::no_entry::no_entry_sign::no_mobile_phones::no_pedestrians::no_smoking::non-potable_water::o::o2::ok::on::one::ophiuchus::parking::part_alternation_mark::passport_control::pisces::potable_water::put_litter_in_its_place::radio_button::recycle::red_circle::registered::repeat::repeat_one::restroom::rewind::sa::sagittarius::scorpius::secret::seven::shipit::signal_strength::six::six_pointed_star::small_blue_diamond::small_orange_diamond::small_red_triangle::small_red_triangle_down::soon::sos::symbols::taurus::three::tm::top::trident::twisted_rightwards_arrows::two::u5272::u5408::u55b6::u6307::u6708::u6709::u6e80::u7121::u7533::u7981::u7a7a::underage::up::vibration_mode::virgo::vs::wavy_dash::wc::wheelchair::white_check_mark::white_circle::white_flower::white_large_square::white_medium_small_square::white_medium_square::white_small_square::white_square_button::womens::x::zero: 679 | 680 | ## Insert 681 | 682 | ``` 683 | ^^insert^^ 684 | 685 | ^^*insert italic*^^ *^^insert italic 2^^* 686 | 687 | ^^_insert italic_^^ _^^insert italic 2^^_ 688 | 689 | ^^**insert bold**^^ **^^insert bold 2^^** 690 | 691 | ^^__insert bold__^^ __^^insert bold 2^^__ 692 | 693 | ^^***insert italic bold***^^ ***^^insert italic bold 2^^*** 694 | 695 | ^^___insert italic bold___^^ ___^^insert italic bold 2^^___ 696 | 697 | **^^*insert italic bold*^^** *^^**insert italic bold 2**^^* 698 | 699 | __^^_insert italic bold_^^__ _^^__insert italic bold 2__^^_ 700 | 701 | **^^_insert italic bold_^^** _^^**insert italic bold 2**^^_ 702 | 703 | __^^*insert italic bold*^^__ *^^__insert italic bold 2__^^* 704 | ``` 705 | 706 | ^^insert^^ 707 | 708 | ^^*insert italic*^^ *^^insert italic 2^^* 709 | 710 | ^^_insert italic_^^ _^^insert italic 2^^_ 711 | 712 | ^^**insert bold**^^ **^^insert bold 2^^** 713 | 714 | ^^__insert bold__^^ __^^insert bold 2^^__ 715 | 716 | ^^***insert italic bold***^^ ***^^insert italic bold 2^^*** 717 | 718 | ^^___insert italic bold___^^ ___^^insert italic bold 2^^___ 719 | 720 | **^^*insert italic bold*^^** *^^**insert italic bold 2**^^* 721 | 722 | __^^_insert italic bold_^^__ _^^__insert italic bold 2__^^_ 723 | 724 | **^^_insert italic bold_^^** _^^**insert italic bold 2**^^_ 725 | 726 | __^^*insert italic bold*^^__ *^^__insert italic bold 2__^^* 727 | 728 | ## Progress 729 | 730 | Progress bars are block elements and it is recommened to put a newline before and after. But they will be recognized inline, but they will be on their own line. 731 | 732 | Normally you would just globally set your additional classes: `progressbar(add_classes=candystripe-animate)`, but here we will demonstrate that it works with the `attr_list` extension. It will take inline style. 733 | 734 | To turn off level classes (which are used to decide special colors for certain percentages) you could just use `progressbar(level_class=False)`. 735 | ``` 736 | | Test | Result | 737 | |--------------------|-----------------------------------------------| 738 | |Animated: 0% |[=0% "0%"]{: .candystripe-animate} | 739 | |Animated: 5% |[=5% "5%"]{: .candystripe-animate} | 740 | |Animated: 25% |[=25% "25%"]{: .candystripe-animate} | 741 | |Animated: 45% |[=45% "45%"]{: .candystripe-animate} | 742 | |Animated: 65% |[=65% "65%"]{: .candystripe-animate} | 743 | |Animated: 85% |[=85% "85%"]{: .candystripe-animate} | 744 | |Animated: 100% |[=100% "100%"]{: .candystripe-animate} | 745 | |Division Percentage |[= 212.2/537 "212.2/537 Testing division"] | 746 | |No Label |[= 50%] | 747 | |Inline |Before[= 50% "I'm a block!"]After | 748 | |Gloss and Animated |[= 50% "Gloss"]{: .candystripe-animate .gloss} | 749 | ``` 750 | 751 | | Test | Result | 752 | |--------------------|-----------------------------------------------| 753 | |Animated: 0% |[=0% "0%"]{: .candystripe-animate} | 754 | |Animated: 5% |[=5% "5%"]{: .candystripe-animate} | 755 | |Animated: 25% |[=25% "25%"]{: .candystripe-animate} | 756 | |Animated: 45% |[=45% "45%"]{: .candystripe-animate} | 757 | |Animated: 65% |[=65% "65%"]{: .candystripe-animate} | 758 | |Animated: 85% |[=85% "85%"]{: .candystripe-animate} | 759 | |Animated: 100% |[=100% "100%"]{: .candystripe-animate} | 760 | |Division Percentage |[= 212.2/537 "212.2/537 Testing division"] | 761 | |No Label |[= 50%] | 762 | |Inline |Before[= 50% "I'm a block!"]After | 763 | |Gloss and Animated |[= 50% "Gloss"]{: .candystripe-animate .gloss} | 764 | 765 | ## Neseted Fences 766 | 767 | ```` 768 | ``` 769 | This will still be parsed 770 | as a normal indented code block. 771 | ``` 772 | 773 | ``` 774 | This will still be parsed 775 | as a fenced code block. 776 | ``` 777 | 778 | - This is a list that contains multiple code blocks. 779 | 780 | - Here is an indented block 781 | 782 | ``` 783 | This will still be parsed 784 | as a normal indented code block. 785 | ``` 786 | 787 | - Here is a fenced code block: 788 | 789 | ``` 790 | This will still be parsed 791 | as a fenced code block. 792 | ``` 793 | 794 | > ``` 795 | > Blockquotes? 796 | > Not a problem! 797 | > ``` 798 | ```` 799 | 800 | ``` 801 | This will still be parsed 802 | as a normal indented code block. 803 | ``` 804 | 805 | ``` 806 | This will still be parsed 807 | as a fenced code block. 808 | ``` 809 | 810 | - This is a list that contains multiple code blocks. 811 | 812 | - Here is an indented block 813 | 814 | ``` 815 | This will still be parsed 816 | as a normal indented code block. 817 | ``` 818 | 819 | - Here is a fenced code block: 820 | 821 | ``` 822 | This will still be parsed 823 | as a fenced code block. 824 | ``` 825 | 826 | > ``` 827 | > Blockquotes? 828 | > Not a problem! 829 | > ``` 830 | 831 | ## UML Flow Charts 832 | 833 | ```` 834 | ```flow 835 | st=>start: Start:>http://www.google.com[blank] 836 | e=>end:>http://www.google.com 837 | op1=>operation: My Operation 838 | sub1=>subroutine: My Subroutine 839 | cond=>condition: Yes 840 | or No?:>http://www.google.com 841 | io=>inputoutput: catch something... 842 | 843 | st->op1->cond 844 | cond(yes)->io->e 845 | cond(no)->sub1(right)->op1 846 | ``` 847 | ```` 848 | 849 | ```flow 850 | st=>start: Start:>http://www.google.com[blank] 851 | e=>end:>http://www.google.com 852 | op1=>operation: My Operation 853 | sub1=>subroutine: My Subroutine 854 | cond=>condition: Yes 855 | or No?:>http://www.google.com 856 | io=>inputoutput: catch something... 857 | 858 | st->op1->cond 859 | cond(yes)->io->e 860 | cond(no)->sub1(right)->op1 861 | ``` 862 | 863 | ## UML Sequence Diagrams 864 | 865 | ```` 866 | ```sequence 867 | Title: Here is a title 868 | A->B: Normal line 869 | B-->C: Dashed line 870 | C->>D: Open arrow 871 | D-->>A: Dashed open arrow 872 | ``` 873 | ```` 874 | 875 | ```sequence 876 | Title: Here is a title 877 | A->B: Normal line 878 | B-->C: Dashed line 879 | C->>D: Open arrow 880 | D-->>A: Dashed open arrow 881 | ``` 882 | 883 | ## Math 884 | 885 | $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$, \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\). 886 | 887 | $$ 888 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 889 | $$ 890 | 891 | \[3 < 4\] 892 | 893 | \begin{align} 894 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 895 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 896 | \end{align} 897 | --------------------------------------------------------------------------------