├── .gitignore ├── .no-sublime-package ├── Default.sublime-keymap ├── Devdocs offline.sublime-commands ├── HtmlEntities.json ├── packages.json ├── Devdocs offline.sublime-settings ├── test.py ├── Main.sublime-menu ├── languages.json ├── IsoEntities.json ├── README.md ├── style.css └── DevDocs offline.py /.gitignore: -------------------------------------------------------------------------------- 1 | docs -------------------------------------------------------------------------------- /.no-sublime-package: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Default.sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["ctrl+alt+d"], "command": "devdocs_show_definition"}, 3 | { "keys": ["ctrl+alt+s"], "command": "devdocs_search_symbol"}, 4 | ] 5 | -------------------------------------------------------------------------------- /Devdocs offline.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | {"caption": "Devdocs: Show Definition", "command": "devdocs_show_definition"}, 3 | {"caption": "Devdocs: Search Symbol", "command": "devdocs_search_symbol"}, 4 | {"caption": "Devdocs: All Languages", "command": "devdocs_show_all_languages"}, 5 | {"caption": "Devdocs: Set Default Version", "command": "devdocs_set_default_version"}, 6 | {"caption": "Devdocs: Set Syntax Alias", "command": "devdocs_set_syntax_alias"}, 7 | ] 8 | -------------------------------------------------------------------------------- /HtmlEntities.json: -------------------------------------------------------------------------------- 1 | { 2 | "quot": 34, 3 | "amp": 38, 4 | "lt": 60, 5 | "gt": 62, 6 | 7 | "OElig": 338, 8 | "oelig": 339, 9 | 10 | "Scaron": 352, 11 | "scaron": 353, 12 | "Yuml": 376, 13 | 14 | "circ": 710, 15 | "tilde": 732, 16 | 17 | "ensp": 8194, 18 | "emsp": 8195, 19 | "thinsp": 8201, 20 | "zwnj": 8204, 21 | "zwj": 8205, 22 | "lrm": 8206, 23 | "rlm": 8207, 24 | "ndash": 8211, 25 | "mdash": 8212, 26 | "lsquo": 8216, 27 | "rsquo": 8217, 28 | "sbquo": 8218, 29 | "ldquo": 8220, 30 | "rdquo": 8221, 31 | "bdquo": 8222, 32 | "dagger": 8224, 33 | "Dagger": 8225, 34 | "permil": 8240, 35 | "lsaquo": 8249, 36 | 37 | "rsaquo": 8250, 38 | 39 | "euro": 8364 40 | } 41 | -------------------------------------------------------------------------------- /packages.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "3.0.0", 3 | "packages": [ 4 | { 5 | "name": "DevDocs offline", 6 | "description": "Quick search symbol in devdocs offline plugin for Sublime Text 3", 7 | "author": "hectorqin", 8 | "details": "https://github.com/hectorqin/sublime-devdocs", 9 | "issues": "https://github.com/hectorqin/sublime-devdocs", 10 | "labels": [ 11 | "symbol", 12 | "devdocs", 13 | "offline", 14 | "document" 15 | ], 16 | "releases": [ 17 | { 18 | "sublime_text": ">=3000", 19 | "tags": true 20 | } 21 | ] 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /Devdocs offline.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | // This file is default setting of this plugin, please don't edit this file 3 | 4 | // Download proxy 5 | "http_proxy": "", 6 | 7 | // Max height and width of popup 8 | "popup_max_height": 1080, 9 | "popup_max_width": 1280, 10 | 11 | // Set true to use style file to set custom styles, this is experimental 12 | "use_style": false, 13 | 14 | // Default language version for symbol search 15 | "language_default_version": { 16 | 17 | }, 18 | // Usually, this plugin parse the language type from the syntax setting of the view, this may be not accurate, you can set this configuration to set the syntax alias 19 | "syntax_alias":{ 20 | 21 | }, 22 | // languageWithVersion as key, languageForPath as value. You can set it When the path is wrong. 23 | "language_slug_alias":{ 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import re 2 | import json 3 | import urllib 4 | 5 | language_slug_alias_default = { 6 | "apache": "apache_http_server", 7 | "jquery_core": "jquery", 8 | "jquery_mobile": "jquerymobile", 9 | "jquery_ui": "jqueryui", 10 | "nokogiri2": "nokogiri", 11 | "support_tables": "browser_support_tables", 12 | } 13 | 14 | 15 | def getSetting(key, default=None): 16 | return default 17 | 18 | 19 | def getLanguageSlug(language): 20 | global language_slug_alias_default 21 | language_slug_alias = language_slug_alias_default.copy() 22 | language_slug_alias.update(getSetting('language_slug_alias', {})) 23 | if language_slug_alias.get(language): 24 | return language_slug_alias.get(language) 25 | if language[-1] == '@': 26 | language = language[:-1] 27 | v = language.split('@', 1) 28 | name = v[0].lower() 29 | if len(v) == 1: 30 | return name 31 | version = v[1].lower().replace( 32 | '@', '~').replace('+', 'p').replace('#', 's') 33 | version = re.sub(r"[^a-z0-9\_\.]", "_", version) 34 | return name + "~" + version 35 | 36 | 37 | def getResponseCode(path): 38 | url = 'http://dl.devdocs.io/' + path + '.tar.gz' 39 | response = urllib.urlopen(url) 40 | code = response.getcode() 41 | return code 42 | 43 | 44 | def main(): 45 | badL = [] 46 | with open("./languages.json", 'r') as content: 47 | languages = json.load(content) 48 | for lang in languages: 49 | path = getLanguageSlug(lang) 50 | code = getResponseCode(path) 51 | print("%s ToPath: %s ResponseCode: %d" % (lang, path, code)) 52 | if code != 200: 53 | badL.append((lang, path, code)) 54 | print(badL) 55 | 56 | if __name__ == "__main__": 57 | main() 58 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "mnemonic": "n", 4 | "caption": "Preferences", 5 | "id": "preferences", 6 | "children": [ 7 | { 8 | "mnemonic": "P", 9 | "caption": "Package Settings", 10 | "id": "package-settings", 11 | "children": [ 12 | { 13 | "caption": "DevDocs offline", 14 | "children": [ 15 | { 16 | "caption": "Settings – Default", 17 | "args": { 18 | "file": "${packages}/DevDocs offline/DevDocs offline.sublime-settings" 19 | }, 20 | "command": "open_file" 21 | }, 22 | { 23 | "caption": "Settings – User", 24 | "args": { 25 | "file": "${packages}/User/DevDocs offline.sublime-settings" 26 | }, 27 | "command": "open_file" 28 | }, 29 | { 30 | "caption": "Key Bindings – Default", 31 | "args": { 32 | "file": "${packages}/DevDocs offline/Default.sublime-keymap" 33 | }, 34 | "command": "open_file" 35 | }, 36 | { 37 | "caption": "-" 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | ] 44 | } 45 | ] -------------------------------------------------------------------------------- /languages.json: -------------------------------------------------------------------------------- 1 | ["angular@","angular@2","angularjs@1.6","angularjs@1.5","angularjs@1.4","angularjs@1.3","angularjs@1.2","ansible@2.4","ansible@2.5","ansible@2.6","apache","apache_pig@0.17","apache_pig@0.16","apache_pig@0.15","apache_pig@0.14","apache_pig@0.13","async","backbone","bootstrap@4","bootstrap@3","bottle@0.12","bottle@0.11","bower","c","cpp","cakephp@3.5","cakephp@3.4","cakephp@3.3","cakephp@3.2","cakephp@3.1","cakephp@2.10","cakephp@2.9","cakephp@2.8","cakephp@2.7","chai","chef@12","chef@11","clojure@1.8","clojure@1.7","cmake@3.9","cmake@3.8","cmake@3.7","cmake@3.6","cmake@3.5","codeception","codeceptjs","codeigniter@3","coffeescript@2","coffeescript@1","cordova@7","cordova@6","crystal","css","d","d3@4","d3@3","django@1.11","django@1.10","django@1.9","django@1.8","docker@17","docker@1.13","docker@1.12","docker@1.11","docker@1.10","dojo","dom","dom_events","drupal@8","drupal@7","electron","elixir@1.5","elixir@1.4","elixir@1.3","ember","erlang@20","erlang@19","erlang@18","express","falcon@1.3","falcon@1.2","fish@2.6","fish@2.5","fish@2.4","fish@2.3","fish@2.2","flow","gcc@7","gcc@7 CPP","gcc@6","gcc@6 CPP","gcc@5","gcc@5 CPP","gcc@4","gcc@4 CPP","git","gnu_fortran@7","gnu_fortran@6","gnu_fortran@5","gnu_fortran@4","go","godot@2.1","grunt","haskell@8","haskell@7","haxe@","haxe@C++","haxe@C#","haxe@Flash","haxe@Java","haxe@JavaScript","haxe@Neko","haxe@PHP","haxe@Python","html","http","immutable","influxdata","jasmine","javascript","jest","jquery_core","jquery_mobile","jquery_ui","julia@0.6","julia@0.5","knockout","kotlin","laravel@5.5","laravel@5.4","laravel@5.3","laravel@5.2","laravel@5.1","laravel@4.2","less","liquid","lodash@4","lodash@3","lodash@2","lua@5.3","lua@5.2","lua@5.1","love","marionette@3","marionette@2","markdown","matplotlib@2.0","matplotlib@1.5","meteor@1.5","meteor@1.4","meteor@1.3","mocha","modernizr","moment","mongoose","nginx","nginx_lua_module","nim","node@","node@6 LTS","node@4 LTS","nokogiri2","npm","numpy@1.13","numpy@1.12","numpy@1.11","numpy@1.10","openjdk@8","openjdk@8 GUI","openjdk@8 Web","opentsdb","padrino","pandas@0.20","pandas@0.19","pandas@0.18","perl@5.26","perl@5.24","perl@5.22","perl@5.20","phalcon@3","phalcon@2","phaser","phoenix","php","phpunit@6","phpunit@5","phpunit@4","postgresql@9.6","postgresql@9.5","postgresql@9.4","pug","python@3.6","python@3.5","python@2.7","q","ramda","react","react_native","redis","redux","relay","requirejs","rethinkdb@JavaScript","rethinkdb@Ruby","rethinkdb@Python","rethinkdb@Java","ruby@2.4","ruby@2.3","ruby@2.2","minitest","rails@5.1","rails@5.0","rails@4.2","rails@4.1","rust","sass","scikit_image","scikit_learn","sinon@4","sinon@3","sinon@2","sinon@1","socketio","sqlite","statsmodels","support_tables","svg","symfony@3.3","symfony@3.2","symfony@3.1","symfony@3.0","symfony@2.8","symfony@2.7","tcl_tk","tensorflow@Python","tensorflow@C++","tensorflow@Guide","twig@2","twig@1","typescript","underscore","vagrant","vue@2","vue@1","vulkan","webpack@","webpack@1","xslt_xpath","yarn","yii@2.0","yii@1.1"] -------------------------------------------------------------------------------- /IsoEntities.json: -------------------------------------------------------------------------------- 1 | { 2 | "nbsp": 160, 3 | "iexcl": 161, 4 | "cent": 162, 5 | "pound": 163, 6 | "curren": 164, 7 | "yen": 165, 8 | "brvbar": 166, 9 | "sect": 167, 10 | "uml": 168, 11 | "copy": 169, 12 | "ordf": 170, 13 | "laquo": 171, 14 | "not": 172, 15 | "shy": 173, 16 | "reg": 174, 17 | "macr": 175, 18 | "deg": 176, 19 | "plusmn": 177, 20 | "sup2": 178, 21 | "sup3": 179, 22 | "acute": 180, 23 | "micro": 181, 24 | "para": 182, 25 | "middot": 183, 26 | "cedil": 184, 27 | "sup1": 185, 28 | "ordm": 186, 29 | "raquo": 187, 30 | "frac14": 188, 31 | "frac12": 189, 32 | "frac34": 190, 33 | "iquest": 191, 34 | 35 | "Agrave": 192, 36 | "Aacute": 193, 37 | "Acirc": 194, 38 | "Atilde": 195, 39 | "Auml": 196, 40 | "Aring": 197, 41 | "AElig": 198, 42 | "Ccedil": 199, 43 | "Egrave": 200, 44 | "Eacute": 201, 45 | "Ecirc": 202, 46 | "Euml": 203, 47 | "Igrave": 204, 48 | "Iacute": 205, 49 | "Icirc": 206, 50 | "Iuml": 207, 51 | "ETH": 208, 52 | "Ntilde": 209, 53 | "Ograve": 210, 54 | "Oacute": 211, 55 | "Ocirc": 212, 56 | "Otilde": 213, 57 | "Ouml": 214, 58 | "times": 215, 59 | "Oslash": 216, 60 | "Ugrave": 217, 61 | "Uacute": 218, 62 | "Ucirc": 219, 63 | "Uuml": 220, 64 | "Yacute": 221, 65 | "THORN": 222, 66 | "szlig": 223, 67 | "agrave": 224, 68 | "aacute": 225, 69 | "acirc": 226, 70 | "atilde": 227, 71 | "auml": 228, 72 | "aring": 229, 73 | "aelig": 230, 74 | "ccedil": 231, 75 | "egrave": 232, 76 | "eacute": 233, 77 | "ecirc": 234, 78 | "euml": 235, 79 | "igrave": 236, 80 | "iacute": 237, 81 | "icirc": 238, 82 | "iuml": 239, 83 | "eth": 240, 84 | "ntilde": 241, 85 | "ograve": 242, 86 | "oacute": 243, 87 | "ocirc": 244, 88 | "otilde": 245, 89 | "ouml": 246, 90 | "divide": 247, 91 | "oslash": 248, 92 | "ugrave": 249, 93 | "uacute": 250, 94 | "ucirc": 251, 95 | "uuml": 252, 96 | "yacute": 253, 97 | "thorn": 254, 98 | "yuml": 255, 99 | 100 | 101 | "Alpha": 913, 102 | "Beta": 914, 103 | "Gamma": 915, 104 | "Delta": 916, 105 | "Epsilon": 917, 106 | "Zeta": 918, 107 | "Eta": 919, 108 | "Theta": 920, 109 | "Iota": 921, 110 | "Kappa": 922, 111 | "Lambda": 923, 112 | "Mu": 924, 113 | "Nu": 925, 114 | "Xi": 926, 115 | "Omicron": 927, 116 | "Pi": 928, 117 | "Rho": 929, 118 | "Sigma": 931, 119 | "Tau": 932, 120 | "Upsilon": 933, 121 | "Phi": 934, 122 | "Chi": 935, 123 | "Psi": 936, 124 | "Omega": 937, 125 | 126 | "alpha": 945, 127 | "beta": 946, 128 | "gamma": 947, 129 | "delta": 948, 130 | "epsilon": 949, 131 | "zeta": 950, 132 | "eta": 951, 133 | "theta": 952, 134 | "iota": 953, 135 | "kappa": 954, 136 | "lambda": 955, 137 | "mu": 956, 138 | "nu": 957, 139 | "xi": 958, 140 | "omicron": 959, 141 | "pi": 960, 142 | "rho": 961, 143 | "sigmaf": 962, 144 | "sigma": 963, 145 | "tau": 964, 146 | "upsilon": 965, 147 | "phi": 966, 148 | "chi": 967, 149 | "psi": 968, 150 | "omega": 969, 151 | "thetasym": 977, 152 | "upsih": 978, 153 | "piv": 982 154 | } 155 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Sublime-devdocs 2 | =========================== 3 | **** 4 | ### Author:hector 5 | ### E-mail:hectorqin@163.com 6 | **** 7 | 8 | Quick search symbol in devdocs offline plugin for Sublime Text 3 9 | 10 | 11 | ### Installation 12 | 13 | The easiest way to install is using [Package Control][pc], where [Sublime-devdocs][theme] is listed as **`Devdocs offline`**. 14 | 15 | 1. Open `Command Palette` using menu item `Tools → Command Palette...` 16 | 17 | 2. Choose `Package Control: Install Package` 18 | 19 | 3. Find `Devdocs offline` and hit `Enter` 20 | 21 | Or install it by downloading the zip, extract it and put it into the package dir of sublime, rename it to "Devdocs offline", and then it may work fine! 22 | 23 | *** 24 | 25 | ### How to use 26 | 27 | 1. Open `Command Palette` using menu item `Tools → Command Palette...` 28 | 29 | 2. Choose `Devdocs: All Languages` 30 | 31 | 3. Search what language you need and hit `Enter`. It will download the language docs from [devdocs.io][devdocs.io] 32 | 33 | 4. After download, you can use the commands the following 34 | 35 | *** 36 | 37 | ### Commands 38 | 39 | 1. `Devdocs: All Languages` Show all supported language with version in the panel, and choose language to install or uninstall 40 | 41 | 2. `Devdocs: Show Definition` Search the definition of your selected symbol in the syntax matched language. If found, it will be displayed in the popup 42 | 43 | 3. `Devdocs: Search Symbol` Search symbol in a quick panel, choose item to show the definition of symbol 44 | 45 | 4. `Devdocs: Set Default Version` Set the syntax matched language default search version when the language has many versions 46 | 47 | 5. `Devdocs: Set Syntax Alias` Set the syntax matched to which language, it's useful when the plugin can't identify the language of the syntax 48 | 49 | *** 50 | 51 | ### Settings 52 | 53 | 1. Default Settings 54 | 55 | ```js 56 | { 57 | // This file is default setting of this plugin, please don't edit this file 58 | 59 | // Download proxy 60 | "http_proxy": "", 61 | 62 | // Max height and width of popup 63 | "popup_max_height": 1080, 64 | "popup_max_width": 1280, 65 | 66 | // Set true to use style file to set custom styles, this is experimental 67 | "use_style": false, 68 | 69 | // Default language version for symbol search 70 | "language_default_version": { 71 | 72 | }, 73 | // Usually, this plugin parse the language type from the syntax setting of the view, this may be not accurate, you can set this configuration to set the syntax alias 74 | "syntax_alias":{ 75 | 76 | }, 77 | // languageWithVersion as key, languageForPath as value. You can set it When the path is wrong. 78 | "language_slug_alias":{ 79 | 80 | } 81 | } 82 | ``` 83 | 84 | 2. If you want to modify the setting, please use menu item `Preferences → Package Settings → Devdocs offline → Settings – User` 85 | 86 | *** 87 | 88 | ### keys 89 | 90 | ```js 91 | [ 92 | { "keys": ["ctrl+alt+d"], "command": "devdocs_show_definition"}, 93 | { "keys": ["ctrl+alt+s"], "command": "devdocs_search_symbol"}, 94 | ] 95 | ``` 96 | 97 | ### License 98 | 99 | [Apache](all/COPYING) 100 | 101 | 102 | 103 | [pc]: https://packagecontrol.io/ 104 | [devdocs.io]: https://devdocs.io "devdocs.io" 105 | [theme]: https://packagecontrol.io/packages/DevDocs%20offline 106 | 107 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | #outer{background-color:#f2f2f2;} 2 | #container{margin:10px;color:#000;} 3 | .phpcode,.note,.tip,.classsynopsis,.methodsynopsis,.warning,.informaltable,.caution{padding:10px} 4 | .phpcode,.note,.classsynopsis,.methodsynopsis,.doctable.informaltable{background-color:#fff} 5 | .tip{background-color:#D9E6F2} 6 | .warning{background-color:#F4DFDF} 7 | .caution{background-color:#FCFCE9} 8 | .methodsynopsis{color:#737373;} 9 | span.type,.parameter{color: #693} 10 | .methodname{color:#369;} 11 | code.parameter{color:#369;} 12 | h1,h2,h3,h4,h5,h6{color: #793862;} 13 | .horizontal-rule{background-color: #793862;padding: 0.5px;margin-bottom: 10px} 14 | .border{padding:1;margin:10px 0;} 15 | .border-blue{background-color:#9FBFDF} 16 | .border-gray{background-color:#d9d9d9} 17 | .border-pink{background-color:#eabfbf} 18 | .border-yellow{background-color:#E2E2D1} 19 | pre{white-space: pre-wrap;} 20 | .dd{margin-left: 1.5em} 21 | a.constant{color:#420;} 22 | 23 | /*pre, ._redis>.example, ._toc, ._docs-links, ._bootstrap a.thumbnail { 24 | background: #fafafa; 25 | border: 1px solid #d8d8d8; 26 | border-radius: 3px 27 | } 28 | 29 | ._block-heading, ._apache_pig h2, ._bower h2, ._chai h2, ._codeceptjs h2, ._docker h2, ._electron h2, ._fish h2, ._flow h2, ._gnu h2, ._grunt h2, ._haxe h2, ._immutable h2, ._influxdata h2, ._jasmine h2, ._jest h2, ._less h2, ._lodash h2, ._marionette h2, ._markdown h2, ._mocha h2, ._mongoose h2, ._nim h2, ._redux h2, ._requirejs h2, ._simple h2, ._typescript h2, ._vagrant h2, ._vulkan h2, ._yarn h2, ._angular h2, ._apache h2, ._async h2, ._bootstrap h2, ._cakephp h2, ._codeception h2, ._coffeescript h2, ._cordova h2, ._crystal h2, ._dojo h2, ._elixir h2, ._ember h2, ._erlang h2, ._express h2, ._github h2, ._go h2, ._julia h2, ._liquid h2, ._love h2, ._lua h2, ._meteor h2, ._npm h2, ._openjdk h2, ._perl h2, ._phalcon h2, ._phaser h2, ._phpunit h2, ._pug h2, ._ramda h2, ._react_native h2, ._rethinkdb h2, ._rubydoc h2, ._rust h2, ._sinon h2, ._sphinx_simple h2, ._sqlite h2, ._tcl_tk h2, ._tensorflow h2, ._vue h2, ._webpack h2, ._yard h2, ._yii h2, ._angularjs h2, ._c>h2, ._c>h3, ._clojure h2:not([id]), ._d h2, ._d3>h2, ._drupal h3, ._git>h2, ._haskell-api>h2, ._jquery .section-title, ._jquery .entry-wrapper>h3, ._jquery .underline, ._knockout>h2, ._kotlin h2, ._laravel h2, ._mdn>h2, ._modernizr h2, ._moment>h2, ._nginx h4, ._node>h2, ._php h2, ._php h3.title, ._postgres h2, ._rdoc>.description>h2, ._rdoc header>h3, ._rdoc>h2, ._redis>h2, ._rfc-pre>h2, ._socketio>h2, ._sphinx h2, ._support_tables h2, ._underscore>h2, ._angular .pre-title, ._bootstrap div.bs-example, ._ember .pre-title, ._liquid p.code-label, th, ._bootstrap p.bs-example { 30 | color: #333; 31 | background: #f5f5f5; 32 | border: 1px solid #d8d8d8; 33 | border-radius: 3px 34 | } 35 | 36 | ._block-heading, ._apache_pig h2, ._bower h2, ._chai h2, ._codeceptjs h2, ._docker h2, ._electron h2, ._fish h2, ._flow h2, ._gnu h2, ._grunt h2, ._haxe h2, ._immutable h2, ._influxdata h2, ._jasmine h2, ._jest h2, ._less h2, ._lodash h2, ._marionette h2, ._markdown h2, ._mocha h2, ._mongoose h2, ._nim h2, ._redux h2, ._requirejs h2, ._simple h2, ._typescript h2, ._vagrant h2, ._vulkan h2, ._yarn h2, ._angular h2, ._apache h2, ._async h2, ._bootstrap h2, ._cakephp h2, ._codeception h2, ._coffeescript h2, ._cordova h2, ._crystal h2, ._dojo h2, ._elixir h2, ._ember h2, ._erlang h2, ._express h2, ._github h2, ._go h2, ._julia h2, ._liquid h2, ._love h2, ._lua h2, ._meteor h2, ._npm h2, ._openjdk h2, ._perl h2, ._phalcon h2, ._phaser h2, ._phpunit h2, ._pug h2, ._ramda h2, ._react_native h2, ._rethinkdb h2, ._rubydoc h2, ._rust h2, ._sinon h2, ._sphinx_simple h2, ._sqlite h2, ._tcl_tk h2, ._tensorflow h2, ._vue h2, ._webpack h2, ._yard h2, ._yii h2, ._angularjs h2, ._c>h2, ._c>h3, ._clojure h2:not([id]), ._d h2, ._d3>h2, ._drupal h3, ._git>h2, ._haskell-api>h2, ._jquery .section-title, ._jquery .entry-wrapper>h3, ._jquery .underline, ._knockout>h2, ._kotlin h2, ._laravel h2, ._mdn>h2, ._modernizr h2, ._moment>h2, ._nginx h4, ._node>h2, ._php h2, ._php h3.title, ._postgres h2, ._rdoc>.description>h2, ._rdoc header>h3, ._rdoc>h2, ._redis>h2, ._rfc-pre>h2, ._socketio>h2, ._sphinx h2, ._support_tables h2, ._underscore>h2 { 37 | line-height: 1.25rem; 38 | margin: 2em 0 1em; 39 | padding: .5em .75em; 40 | font-size: 1rem; 41 | overflow: hidden 42 | } 43 | 44 | ._angular .pre-title, ._bootstrap div.bs-example, ._ember .pre-title, ._liquid p.code-label { 45 | margin: 0; 46 | padding: .375rem .625rem; 47 | font-size: inherit; 48 | font-weight: normal; 49 | line-height: 1.5; 50 | border-bottom-left-radius: 0; 51 | border-bottom-right-radius: 0 52 | } 53 | 54 | ._angular .pre-title+pre, ._bootstrap div.bs-example+pre, ._ember .pre-title+pre, ._liquid p.code-label+pre { 55 | border-top-left-radius: 0; 56 | border-top-right-radius: 0; 57 | border-top: 0; 58 | margin-top: 0 59 | } 60 | 61 | ._intro-message, ._note, ._apache_pig blockquote, ._bower blockquote, ._chai blockquote, ._codeceptjs blockquote, ._docker blockquote, ._electron blockquote, ._fish blockquote, ._flow blockquote, ._gnu blockquote, ._grunt blockquote, ._haxe blockquote, ._immutable blockquote, ._influxdata blockquote, ._jasmine blockquote, ._jest blockquote, ._less blockquote, ._lodash blockquote, ._marionette blockquote, ._markdown blockquote, ._mocha blockquote, ._mongoose blockquote, ._nim blockquote, ._redux blockquote, ._requirejs blockquote, ._simple blockquote, ._typescript blockquote, ._vagrant blockquote, ._vulkan blockquote, ._yarn blockquote, ._angular blockquote, ._apache blockquote, ._async blockquote, ._bootstrap blockquote, ._cakephp blockquote, ._codeception blockquote, ._coffeescript blockquote, ._cordova blockquote, ._crystal blockquote, ._dojo blockquote, ._elixir blockquote, ._ember blockquote, ._erlang blockquote, ._express blockquote, ._github blockquote, ._go blockquote, ._julia blockquote, ._liquid blockquote, ._love blockquote, ._lua blockquote, ._meteor blockquote, ._npm blockquote, ._openjdk blockquote, ._perl blockquote, ._phalcon blockquote, ._phaser blockquote, ._phpunit blockquote, ._pug blockquote, ._ramda blockquote, ._react_native blockquote, ._rethinkdb blockquote, ._rubydoc blockquote, ._rust blockquote, ._sinon blockquote, ._sphinx_simple blockquote, ._sqlite blockquote, ._tcl_tk blockquote, ._tensorflow blockquote, ._vue blockquote, ._webpack blockquote, ._yard blockquote, ._yii blockquote, ._angular .breadcrumbs, ._angularjs .alert, ._apache .note, ._apache .warning, ._bootstrap .bs-callout, ._c .fmbox, ._cakephp .info, ._codeception .warning, ._codeception .alert, ._cordova .alert, ._d3 blockquote, ._drupal .signature, ._erlang .note, ._erlang .warning, ._express .doc-box, ._git>.callout, ._git>h1+.sectionbody, ._haskell-api .warning, ._jquery #quick-nav, ._jquery .warning, ._julia .footnote, ._julia .note, ._knockout .liveExample, ._knockout blockquote, ._kotlin .api-docs-breadcrumbs, ._laravel blockquote, ._love .note, ._mdn>.note, ._mdn .notice, ._mdn .warning, ._mdn .overheadIndicator, ._mdn .syntaxbox, ._mdn .twopartsyntaxbox, ._mdn .inheritsbox, ._mdn .eval:first-of-type, ._mdn .htmlelt, ._mdn .cssprop, ._meteor .note, ._meteor .warning, ._meteor .subtitle-page, ._modernizr blockquote, ._nginx .note, ._node .api_stability_0, ._node .api_stability_1, ._node .api_stability_2, ._node .api_stability_3, ._node .api_stability_4, ._node .api_stability_5, ._openjdk>ul.inheritance, ._phaser .deprecated-notice, ._php .classsynopsis, ._php .description>.constructorsynopsis, ._php .description>.methodsynopsis, ._php .description>.fieldsynopsis, ._php blockquote.note, ._php div.warning, ._php div.caution, ._php div.tip, ._phpunit .warning, ._phpunit .alert, ._postgres blockquote.NOTE, ._postgres blockquote.IMPORTANT, ._postgres blockquote.TIP, ._postgres blockquote.CAUTION, ._pug .alert, ._rdoc>.meta, ._rdoc .note, ._rdoc .info, ._rdoc .warning, ._react_native .deprecated, ._redis>.metadata, ._rubydoc p.note, ._sphinx .note, ._sphinx .admonition, ._sphinx div.versionadded, ._sphinx div.versionchanged, ._sphinx .deprecated-removed, ._sphinx .deprecated, ._sphinx .topic, ._sphinx_simple .admonition, ._sqlite .todo, ._vue p.tip { 62 | margin: 1.5rem 0; 63 | padding: .5rem .875rem; 64 | background: #f8f8dd; 65 | border: 1px solid #d3d952; 66 | border-radius: 3px 67 | } 68 | 69 | ._apache_pig h3, ._bower h3, ._chai h3, ._codeceptjs h3, ._docker h3, ._electron h3, ._fish h3, ._flow h3, ._gnu h3, ._grunt h3, ._haxe h3, ._immutable h3, ._influxdata h3, ._jasmine h3, ._jest h3, ._less h3, ._lodash h3, ._marionette h3, ._markdown h3, ._mocha h3, ._mongoose h3, ._nim h3, ._redux h3, ._requirejs h3, ._simple h3, ._typescript h3, ._vagrant h3, ._vulkan h3, ._yarn h3, ._angular h3, ._apache h3, ._async h3, ._bootstrap h3, ._cakephp h3, ._codeception h3, ._coffeescript h3, ._cordova h3, ._crystal h3, ._dojo h3, ._elixir h3, ._ember h3, ._erlang h3, ._express h3, ._github h3, ._go h3, ._julia h3, ._liquid h3, ._love h3, ._lua h3, ._meteor h3, ._npm h3, ._openjdk h3, ._perl h3, ._phalcon h3, ._phaser h3, ._phpunit h3, ._pug h3, ._ramda h3, ._react_native h3, ._rethinkdb h3, ._rubydoc h3, ._rust h3, ._sinon h3, ._sphinx_simple h3, ._sqlite h3, ._tcl_tk h3, ._tensorflow h3, ._vue h3, ._webpack h3, ._yard h3, ._yii h3, ._angularjs .defs>li>h3:first-child, ._c>h4, ._cakephp h4, ._clojure h2[id], ._clojure h3, ._codeception h4, ._d h3, ._d .d_decl, ._d3>h3, ._d3>h6, ._github h4, ._haskell-api>h3, ._haskell-api p.src, ._jquery .signature>.name, ._jquery .api-item>h3, ._knockout>h3, ._kotlin h3, ._laravel h3, ._mdn>h3, ._modernizr h3, ._moment>h3, ._node>h3, ._node>h4, ._perl>h4, ._postgres .VARIABLELIST dt, ._rdoc .method-heading, ._rfc-pre>h3, ._rfc-pre>h4, ._rust h4, ._sinon h4, ._socketio>h3, ._sphinx h3, ._sphinx>dl:not(.docutils)>dt, ._sphinx dd>dl:not(.docutils)>dt, ._sqlite dt, ._tensorflow h4, ._shortcut-code, ._label, ._apache_pig p>code, ._bower p>code, ._chai p>code, ._codeceptjs p>code, ._docker p>code, ._electron p>code, ._fish p>code, ._flow p>code, ._gnu p>code, ._grunt p>code, ._haxe p>code, ._immutable p>code, ._influxdata p>code, ._jasmine p>code, ._jest p>code, ._less p>code, ._lodash p>code, ._marionette p>code, ._markdown p>code, ._mocha p>code, ._mongoose p>code, ._nim p>code, ._redux p>code, ._requirejs p>code, ._simple p>code, ._typescript p>code, ._vagrant p>code, ._vulkan p>code, ._yarn p>code, ._angular p>code, ._apache p>code, ._async p>code, ._bootstrap p>code, ._cakephp p>code, ._codeception p>code, ._coffeescript p>code, ._cordova p>code, ._crystal p>code, ._dojo p>code, ._elixir p>code, ._ember p>code, ._erlang p>code, ._express p>code, ._github p>code, ._go p>code, ._julia p>code, ._liquid p>code, ._love p>code, ._lua p>code, ._meteor p>code, ._npm p>code, ._openjdk p>code, ._perl p>code, ._phalcon p>code, ._phaser p>code, ._phpunit p>code, ._pug p>code, ._ramda p>code, ._react_native p>code, ._rethinkdb p>code, ._rubydoc p>code, ._rust p>code, ._sinon p>code, ._sphinx_simple p>code, ._sqlite p>code, ._tcl_tk p>code, ._tensorflow p>code, ._vue p>code, ._webpack p>code, ._yard p>code, ._yii p>code, ._apache_pig li>code, ._bower li>code, ._chai li>code, ._codeceptjs li>code, ._docker li>code, ._electron li>code, ._fish li>code, ._flow li>code, ._gnu li>code, ._grunt li>code, ._haxe li>code, ._immutable li>code, ._influxdata li>code, ._jasmine li>code, ._jest li>code, ._less li>code, ._lodash li>code, ._marionette li>code, ._markdown li>code, ._mocha li>code, ._mongoose li>code, ._nim li>code, ._redux li>code, ._requirejs li>code, ._simple li>code, ._typescript li>code, ._vagrant li>code, ._vulkan li>code, ._yarn li>code, ._angular li>code, ._apache li>code, ._async li>code, ._bootstrap li>code, ._cakephp li>code, ._codeception li>code, ._coffeescript li>code, ._cordova li>code, ._crystal li>code, ._dojo li>code, ._elixir li>code, ._ember li>code, ._erlang li>code, ._express li>code, ._github li>code, ._go li>code, ._julia li>code, ._liquid li>code, ._love li>code, ._lua li>code, ._meteor li>code, ._npm li>code, ._openjdk li>code, ._perl li>code, ._phalcon li>code, ._phaser li>code, ._phpunit li>code, ._pug li>code, ._ramda li>code, ._react_native li>code, ._rethinkdb li>code, ._rubydoc li>code, ._rust li>code, ._sinon li>code, ._sphinx_simple li>code, ._sqlite li>code, ._tcl_tk li>code, ._tensorflow li>code, ._vue li>code, ._webpack li>code, ._yard li>code, ._yii li>code, ._apache_pig td>code, ._bower td>code, ._chai td>code, ._codeceptjs td>code, ._docker td>code, ._electron td>code, ._fish td>code, ._flow td>code, ._gnu td>code, ._grunt td>code, ._haxe td>code, ._immutable td>code, ._influxdata td>code, ._jasmine td>code, ._jest td>code, ._less td>code, ._lodash td>code, ._marionette td>code, ._markdown td>code, ._mocha td>code, ._mongoose td>code, ._nim td>code, ._redux td>code, ._requirejs td>code, ._simple td>code, ._typescript td>code, ._vagrant td>code, ._vulkan td>code, ._yarn td>code, ._angular td>code, ._apache td>code, ._async td>code, ._bootstrap td>code, ._cakephp td>code, ._codeception td>code, ._coffeescript td>code, ._cordova td>code, ._crystal td>code, ._dojo td>code, ._elixir td>code, ._ember td>code, ._erlang td>code, ._express td>code, ._github td>code, ._go td>code, ._julia td>code, ._liquid td>code, ._love td>code, ._lua td>code, ._meteor td>code, ._npm td>code, ._openjdk td>code, ._perl td>code, ._phalcon td>code, ._phaser td>code, ._phpunit td>code, ._pug td>code, ._ramda td>code, ._react_native td>code, ._rethinkdb td>code, ._rubydoc td>code, ._rust td>code, ._sinon td>code, ._sphinx_simple td>code, ._sqlite td>code, ._tcl_tk td>code, ._tensorflow td>code, ._vue td>code, ._webpack td>code, ._yard td>code, ._yii td>code, ._apache_pig blockquote>code, ._bower blockquote>code, ._chai blockquote>code, ._codeceptjs blockquote>code, ._docker blockquote>code, ._electron blockquote>code, ._fish blockquote>code, ._flow blockquote>code, ._gnu blockquote>code, ._grunt blockquote>code, ._haxe blockquote>code, ._immutable blockquote>code, ._influxdata blockquote>code, ._jasmine blockquote>code, ._jest blockquote>code, ._less blockquote>code, ._lodash blockquote>code, ._marionette blockquote>code, ._markdown blockquote>code, ._mocha blockquote>code, ._mongoose blockquote>code, ._nim blockquote>code, ._redux blockquote>code, ._requirejs blockquote>code, ._simple blockquote>code, ._typescript blockquote>code, ._vagrant blockquote>code, ._vulkan blockquote>code, ._yarn blockquote>code, ._angular blockquote>code, ._apache blockquote>code, ._async blockquote>code, ._bootstrap blockquote>code, ._cakephp blockquote>code, ._codeception blockquote>code, ._coffeescript blockquote>code, ._cordova blockquote>code, ._crystal blockquote>code, ._dojo blockquote>code, ._elixir blockquote>code, ._ember blockquote>code, ._erlang blockquote>code, ._express blockquote>code, ._github blockquote>code, ._go blockquote>code, ._julia blockquote>code, ._liquid blockquote>code, ._love blockquote>code, ._lua blockquote>code, ._meteor blockquote>code, ._npm blockquote>code, ._openjdk blockquote>code, ._perl blockquote>code, ._phalcon blockquote>code, ._phaser blockquote>code, ._phpunit blockquote>code, ._pug blockquote>code, ._ramda blockquote>code, ._react_native blockquote>code, ._rethinkdb blockquote>code, ._rubydoc blockquote>code, ._rust blockquote>code, ._sinon blockquote>code, ._sphinx_simple blockquote>code, ._sqlite blockquote>code, ._tcl_tk blockquote>code, ._tensorflow blockquote>code, ._vue blockquote>code, ._webpack blockquote>code, ._yard blockquote>code, ._yii blockquote>code, ._apache_pig dd>code, ._bower dd>code, ._chai dd>code, ._codeceptjs dd>code, ._docker dd>code, ._electron dd>code, ._fish dd>code, ._flow dd>code, ._gnu dd>code, ._grunt dd>code, ._haxe dd>code, ._immutable dd>code, ._influxdata dd>code, ._jasmine dd>code, ._jest dd>code, ._less dd>code, ._lodash dd>code, ._marionette dd>code, ._markdown dd>code, ._mocha dd>code, ._mongoose dd>code, ._nim dd>code, ._redux dd>code, ._requirejs dd>code, ._simple dd>code, ._typescript dd>code, ._vagrant dd>code, ._vulkan dd>code, ._yarn dd>code, ._angular dd>code, ._apache dd>code, ._async dd>code, ._bootstrap dd>code, ._cakephp dd>code, ._codeception dd>code, ._coffeescript dd>code, ._cordova dd>code, ._crystal dd>code, ._dojo dd>code, ._elixir dd>code, ._ember dd>code, ._erlang dd>code, ._express dd>code, ._github dd>code, ._go dd>code, ._julia dd>code, ._liquid dd>code, ._love dd>code, ._lua dd>code, ._meteor dd>code, ._npm dd>code, ._openjdk dd>code, ._perl dd>code, ._phalcon dd>code, ._phaser dd>code, ._phpunit dd>code, ._pug dd>code, ._ramda dd>code, ._react_native dd>code, ._rethinkdb dd>code, ._rubydoc dd>code, ._rust dd>code, ._sinon dd>code, ._sphinx_simple dd>code, ._sqlite dd>code, ._tcl_tk dd>code, ._tensorflow dd>code, ._vue dd>code, ._webpack dd>code, ._yard dd>code, ._yii dd>code, ._angularjs p>code, ._angularjs li>code, ._angularjs td>code, ._bootstrap h4>code, ._bootstrap h5>code, ._bootstrap strong>code, ._bootstrap .text-danger, ._c code, ._c .t-mark, ._c .t-mark-rev, ._cakephp code, ._cakephp p>.label, ._cakephp dt>.label, ._cakephp div>.label, ._crystal a.signature, ._crystal .superclass>a, ._d p>code, ._d li>code, ._d td>code, ._d dd>code, ._d3 code, ._drupal span.api-deprecated, ._erlang code.code, ._git code, ._haskell-api dt>code, ._haskell-api .complexity, ._haskell-api .version, ._jquery p>code, ._jquery li>code, ._knockout p>code, ._kotlin code, ._laravel p>code, ._laravel h4>code, ._love .label, ._love dt>code, ._mdn p>code, ._mdn li>code, ._mdn .inlineIndicator, ._meteor dt>code, ._modernizr code, ._moment code, ._nginx dt>code, ._node p>code, ._node li>code, ._node .type, ._node .api_metadata, ._php strong>code, ._php dt>code, ._postgres p>code, ._pug h4>code, ._redis p>code, ._rubydoc span.note, ._rust em.stab, ._rust span.stab, ._socketio code, ._sphinx p>code, ._sphinx li>code, ._sphinx dd>code, ._sphinx .docutils>dt>code, ._sphinx_simple code, ._support_tables code, ._underscore .header+code { 70 | margin: 0 1px; 71 | padding: 1px 4px 2px; 72 | background: #f4f4f4; 73 | border-radius: 3px 74 | } 75 | 76 | ._apache_pig h3, ._bower h3, ._chai h3, ._codeceptjs h3, ._docker h3, ._electron h3, ._fish h3, ._flow h3, ._gnu h3, ._grunt h3, ._haxe h3, ._immutable h3, ._influxdata h3, ._jasmine h3, ._jest h3, ._less h3, ._lodash h3, ._marionette h3, ._markdown h3, ._mocha h3, ._mongoose h3, ._nim h3, ._redux h3, ._requirejs h3, ._simple h3, ._typescript h3, ._vagrant h3, ._vulkan h3, ._yarn h3, ._angular h3, ._apache h3, ._async h3, ._bootstrap h3, ._cakephp h3, ._codeception h3, ._coffeescript h3, ._cordova h3, ._crystal h3, ._dojo h3, ._elixir h3, ._ember h3, ._erlang h3, ._express h3, ._github h3, ._go h3, ._julia h3, ._liquid h3, ._love h3, ._lua h3, ._meteor h3, ._npm h3, ._openjdk h3, ._perl h3, ._phalcon h3, ._phaser h3, ._phpunit h3, ._pug h3, ._ramda h3, ._react_native h3, ._rethinkdb h3, ._rubydoc h3, ._rust h3, ._sinon h3, ._sphinx_simple h3, ._sqlite h3, ._tcl_tk h3, ._tensorflow h3, ._vue h3, ._webpack h3, ._yard h3, ._yii h3, ._angularjs .defs>li>h3:first-child, ._c>h4, ._cakephp h4, ._clojure h2[id], ._clojure h3, ._codeception h4, ._d h3, ._d .d_decl, ._d3>h3, ._d3>h6, ._github h4, ._haskell-api>h3, ._haskell-api p.src, ._jquery .signature>.name, ._jquery .api-item>h3, ._knockout>h3, ._kotlin h3, ._laravel h3, ._mdn>h3, ._modernizr h3, ._moment>h3, ._node>h3, ._node>h4, ._perl>h4, ._postgres .VARIABLELIST dt, ._rdoc .method-heading, ._rfc-pre>h3, ._rfc-pre>h4, ._rust h4, ._sinon h4, ._socketio>h3, ._sphinx h3, ._sphinx>dl:not(.docutils)>dt, ._sphinx dd>dl:not(.docutils)>dt, ._sqlite dt, ._tensorflow h4 { 77 | display: block; 78 | line-height: 1.375rem; 79 | margin: 2em 0 1em; 80 | padding-left: .5em; 81 | padding-right: .5em; 82 | overflow: hidden; 83 | font-size: inherit; 84 | color: #333; 85 | border: 1px solid #d8d8d8; 86 | border-radius: 2px 87 | } 88 | 89 | ._cakephp p>.label, ._cakephp dt>.label, ._cakephp div>.label { 90 | background: #f8f8dd; 91 | border-color: #d3d952 92 | } 93 | 94 | ._intro-message, ._note-green, ._angular .banner, ._angularjs .alert-success, ._git>.callout, ._git>h1+.sectionbody, ._love .note-green, ._node .api_stability_3, ._node .api_stability_4, ._php div.tip, ._postgres blockquote.TIP, ._redis>.metadata, ._sphinx_simple .admonition.tip, ._angular code.stable, ._c .t-mark, ._c .t-mark-rev, ._haskell-api .complexity, ._haskell-api .version, ._love .label-green { 95 | background: #e7f8e1; 96 | border-color: #89da70 97 | } 98 | 99 | ._angular .alert.is-helpful, ._angular .breadcrumbs, ._bootstrap .bs-callout-info, ._d3 blockquote, ._drupal .signature, ._jquery #quick-nav, ._laravel blockquote.tip, ._mdn .htmlelt, ._mdn .cssprop, ._meteor .subtitle-page, ._node .api_stability_5, ._openjdk>ul.inheritance, ._php .classsynopsis, ._php .description>.constructorsynopsis, ._php .description>.methodsynopsis, ._php .description>.fieldsynopsis, ._rdoc>.meta, ._rdoc .info, ._webpack blockquote.tip, ._apache_pig h3, ._bower h3, ._chai h3, ._codeceptjs h3, ._docker h3, ._electron h3, ._fish h3, ._flow h3, ._gnu h3, ._grunt h3, ._haxe h3, ._immutable h3, ._influxdata h3, ._jasmine h3, ._jest h3, ._less h3, ._lodash h3, ._marionette h3, ._markdown h3, ._mocha h3, ._mongoose h3, ._nim h3, ._redux h3, ._requirejs h3, ._simple h3, ._typescript h3, ._vagrant h3, ._vulkan h3, ._yarn h3, ._angular h3, ._apache h3, ._async h3, ._bootstrap h3, ._cakephp h3, ._codeception h3, ._coffeescript h3, ._cordova h3, ._crystal h3, ._dojo h3, ._elixir h3, ._ember h3, ._erlang h3, ._express h3, ._github h3, ._go h3, ._julia h3, ._liquid h3, ._love h3, ._lua h3, ._meteor h3, ._npm h3, ._openjdk h3, ._perl h3, ._phalcon h3, ._phaser h3, ._phpunit h3, ._pug h3, ._ramda h3, ._react_native h3, ._rethinkdb h3, ._rubydoc h3, ._rust h3, ._sinon h3, ._sphinx_simple h3, ._sqlite h3, ._tcl_tk h3, ._tensorflow h3, ._vue h3, ._webpack h3, ._yard h3, ._yii h3, ._angularjs .defs>li>h3:first-child, ._c>h4, ._clojure h2[id], ._clojure h3, ._d h3, ._d .d_decl, ._d3>h6, ._haskell-api p.src, ._jquery .signature>.name, ._jquery .api-item>h3, ._knockout>h3, ._kotlin h3, ._laravel h3, ._mdn>h3, ._modernizr h3, ._moment>h3, ._node>h3, ._postgres .VARIABLELIST dt, ._rdoc .method-heading, ._rfc-pre>h3, ._socketio>h3, ._sphinx>dl:not(.docutils)>dt, ._sqlite dt { 100 | background: #d4f3fd; 101 | border-color: #94bbeb 102 | } 103 | 104 | ._php div.caution, ._postgres blockquote.CAUTION, ._pug .alert-danger, ._react_native .deprecated, ._rethinkdb .infobox-alert, ._sphinx .important, ._sphinx_simple .admonition.warning, ._angular code.experimental, ._mdn .nonStandard, ._mdn .projectSpecific, ._mdn .experimental, ._rust em.stab.unstable, ._rust span.stab.unstable { 105 | background: #fbe6d1; 106 | border-color: #ec8b01 107 | } 108 | 109 | ._angular .alert.is-important, ._angularjs .alert-error, ._apache .warning, ._bootstrap .bs-callout-danger, ._codeception .alert-danger, ._erlang .warning, ._express .doc-warn, ._love .note-red, ._mdn .warning, ._meteor .warning, ._node .api_stability_0, ._node .api_stability_1, ._php div.warning, ._phpunit .alert-danger, ._rdoc .warning, ._sphinx .warning, ._sphinx .deprecated-removed, ._sphinx .deprecated, ._sqlite .todo, ._angular code.deprecated, ._bootstrap .text-danger, ._drupal span.api-deprecated, ._love .label-red, ._mdn .deprecated, ._mdn .obsolete, ._rubydoc span.note.private { 110 | background: #fed5d3; 111 | border-color: #dc7874 112 | } 113 | */ -------------------------------------------------------------------------------- /DevDocs offline.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | 4 | import re 5 | import os 6 | import shutil 7 | import tarfile 8 | import webbrowser 9 | import time 10 | import urllib 11 | from Default import symbol as sublime_symbol 12 | from html.parser import HTMLParser 13 | 14 | package_name = "DevDocs offline" 15 | setting_file = package_name + '.sublime-settings' 16 | entities = { 17 | "iso": False, 18 | "html": False 19 | } 20 | language_slug_alias_default = { 21 | "apache": "apache_http_server", 22 | "jquery_core": "jquery", 23 | "jquery_mobile": "jquerymobile", 24 | "jquery_ui": "jqueryui", 25 | "nokogiri2": "nokogiri", 26 | "support_tables": "browser_support_tables", 27 | } 28 | all_languages = None 29 | all_languages_display = None 30 | installed_languages = None 31 | languages_index = {} 32 | 33 | installed_tip = { 34 | 'toggle': 'Installed, click to uninstall', 35 | 'set_as_default': 'Installed, click to set as default version' 36 | } 37 | uninstalled_tip = { 38 | 'toggle': 'Uninstalled, click to install', 39 | 'set_as_default': 'Uninstalled, click to install and set as default version' 40 | } 41 | 42 | currentSettings = None 43 | popup_default_max_width = 800 44 | popup_default_max_height = 300 45 | 46 | 47 | def plugin_loaded(): 48 | global currentSettings, setting_file 49 | currentSettings = sublime.load_settings(setting_file) 50 | docs_path = getDocsPath(True) 51 | if not os.path.isdir(docs_path): 52 | os.makedirs(docs_path) 53 | 54 | if not callable(sublime_symbol.symbol_at_point) or not callable(sublime_symbol.navigate_to_symbol): 55 | sublime.error_message( 56 | 'Cannot find symbol_at_point from Default.sublime-package\n\nPlease restore the file which usually replaced by outdated localizations') 57 | 58 | 59 | def getSetting(key, default=None): 60 | global currentSettings 61 | return currentSettings.get(key, default) 62 | 63 | 64 | def setSetting(key, value): 65 | global currentSettings, setting_file 66 | currentSettings.set(key, value) 67 | sublime.save_settings(setting_file) 68 | 69 | 70 | def getAllLanguages(): 71 | global all_languages 72 | if all_languages == None: 73 | all_languages = sublime.decode_value( 74 | sublime.load_resource(getPackagePath() + '/languages.json')) 75 | return all_languages 76 | 77 | 78 | def checkAllLanguagesForDisplay(update=False, tipType='toggle'): 79 | global all_languages_display 80 | if all_languages_display == None: 81 | all_languages_display = [] 82 | languages = getAllLanguages() 83 | for key, language in enumerate(languages): 84 | all_languages_display.append([language, uninstalled_tip[tipType]]) 85 | 86 | installed_lgs = getAllInstalledLanguages(update) 87 | for key, language in enumerate(all_languages_display): 88 | if installed_lgs.get(getLanguageSlug(language[0])) != None: 89 | all_languages_display[key][1] = installed_tip[tipType] 90 | else: 91 | all_languages_display[key][1] = uninstalled_tip[tipType] 92 | 93 | return all_languages_display 94 | 95 | 96 | def getAllInstalledLanguages(update=False): 97 | global installed_languages 98 | changed = False 99 | if installed_languages == None or update: 100 | if os.path.isfile(getDocsPath(True) + '/docs.json'): 101 | installed_languages = sublime.decode_value( 102 | sublime.load_resource(getDocsPath() + '/docs.json')) 103 | else: 104 | installed_languages = {} 105 | changed = True 106 | for _key in list(installed_languages): 107 | language = installed_languages[_key] 108 | if not os.path.isfile(getLanguagePath(language["slug"], True) + '/index.json'): 109 | installed_languages.pop(_key) 110 | changed = True 111 | if languages_index.get(_key) != None: 112 | languages_index.pop(_key) 113 | if changed: 114 | saveInstalledLanguages() 115 | return installed_languages 116 | 117 | 118 | def saveInstalledLanguages(): 119 | global installed_languages 120 | with open(getDocsPath(True) + '/docs.json', 'w') as f: 121 | f.write(sublime.encode_value(installed_languages, True)) 122 | 123 | 124 | def isInstalled(language, update=False): 125 | installed_lgs = getAllInstalledLanguages(update) 126 | if installed_lgs.get(getLanguageSlug(language)) != None: 127 | return True 128 | else: 129 | return False 130 | 131 | 132 | def setSyntaxAlias(syntax, alias): 133 | syntax_alias = getSetting('syntax_alias', {}) 134 | syntax_alias[syntax] = alias 135 | setSetting('syntax_alias', syntax_alias) 136 | 137 | 138 | def getSyntaxAlias(syntax): 139 | syntax_alias = getSetting('syntax_alias', {}) 140 | if syntax_alias.get(syntax): 141 | return syntax_alias.get(syntax) 142 | else: 143 | return False 144 | 145 | 146 | def setLanguageDefaultVersion(language, version): 147 | language_default_version = getSetting('language_default_version', {}) 148 | language_default_version[language] = version 149 | setSetting('language_default_version', language_default_version) 150 | 151 | 152 | def getLanguageDefaultVersion(language): 153 | language_default_version = getSetting('language_default_version', {}) 154 | if language_default_version.get(language): 155 | return language_default_version.get(language) 156 | else: 157 | return language 158 | 159 | 160 | def searchInAllLanguages(name, tipType='toggle'): 161 | languages = getAllLanguages() 162 | search_languages_display = [] 163 | for key, language in enumerate(languages): 164 | if name in language: 165 | if isInstalled(language): 166 | search_languages_display.append( 167 | [language, installed_tip[tipType]]) 168 | else: 169 | search_languages_display.append( 170 | [language, uninstalled_tip[tipType]]) 171 | return search_languages_display 172 | 173 | 174 | def getPackagePath(absolute=False): 175 | if not absolute: 176 | return 'Packages' + '/' + package_name 177 | else: 178 | return sublime.packages_path() + '/' + package_name 179 | 180 | 181 | def getDocsPath(absolute=False): 182 | return getPackagePath(absolute) + '/docs' 183 | 184 | 185 | def getLanguagePath(language, absolute=False): 186 | return getDocsPath(absolute) + '/' + language 187 | 188 | 189 | def getLanguageSlug(language): 190 | global language_slug_alias_default 191 | language_slug_alias = language_slug_alias_default.copy() 192 | language_slug_alias.update(getSetting('language_slug_alias', {})) 193 | if language_slug_alias.get(language): 194 | return language_slug_alias.get(language) 195 | if language[-1] == '@': 196 | language = language[:-1] 197 | v = language.split('@', 1) 198 | name = v[0].lower() 199 | if len(v) == 1: 200 | return name 201 | version = v[1].lower().replace( 202 | '@', '~').replace('+', 'p').replace('#', 's') 203 | version = re.sub(r"[^a-z0-9\_\.]", "_", version) 204 | return name + "~" + version 205 | 206 | 207 | def parseViewLanguage(view): 208 | syntax = view.settings().get('syntax') 209 | print("Now view syntax " + syntax) 210 | alias = getSyntaxAlias(syntax) 211 | if alias: 212 | print("Found view syntax alias " + alias) 213 | return getLanguageDefaultVersion(alias), alias 214 | matchObj = re.search(r'([^\/]*)\.', syntax) 215 | if matchObj: 216 | language = matchObj.group(1).lower() 217 | else: 218 | language = "php" 219 | return getLanguageDefaultVersion(language), language 220 | 221 | 222 | def getLanguageIndex(language): 223 | global languages_index 224 | if not languages_index.get(language): 225 | index_json = sublime.decode_value( 226 | sublime.load_resource(getLanguagePath(language) + '/index.json')) 227 | languages_index[language] = index_json["entries"] 228 | return languages_index[language] 229 | 230 | 231 | def getAllSymbol(language): 232 | language = getLanguageSlug(language) 233 | indexArr = getLanguageIndex(language) 234 | print(indexArr) 235 | allSymbol = [] 236 | for key, _symbol in enumerate(indexArr): 237 | allSymbol.append(_symbol['name']) 238 | return allSymbol 239 | 240 | 241 | def getSymbolInIndex(symbol, language): 242 | language = getLanguageSlug(language) 243 | indexArr = getLanguageIndex(language) 244 | for key, _symbol in enumerate(indexArr): 245 | if symbol == _symbol['name']: 246 | return _symbol 247 | if symbol + '()' == _symbol['name']: 248 | return _symbol 249 | return None 250 | 251 | 252 | def getSymbolDescriptionFromHtml(path, language): 253 | language = getLanguageSlug(language) 254 | pathinfo = path.split('#') 255 | html_path = getLanguagePath(language) + '/' + pathinfo[0] + '.html' 256 | print("Load From " + html_path) 257 | output = sublime.load_resource(html_path) 258 | dic = { 259 | '—': chr(8212), 260 | '"': '"', 261 | '
': '', 262 | ''': "'", 263 | '&$': "&$", 264 | '»': chr(187), 265 | } 266 | pattern = "|".join(map(re.escape, dic.keys())) 267 | 268 | output = re.sub(pattern, lambda m: dic[m.group()], output) 269 | return output 270 | 271 | 272 | def decodeEntity(xml, category='iso'): 273 | global entities 274 | if not isinstance(xml, str): 275 | return xml 276 | if entities[category]: 277 | forward, reverse = entities[category] 278 | else: 279 | resourceMap = { 280 | "iso": "IsoEntities.json", 281 | "html": "HtmlEntities.json", 282 | } 283 | forward = sublime.decode_value(sublime.load_resource( 284 | getPackagePath() + '/' + resourceMap[category])) 285 | 286 | reverse = dict((v, k) for k, v in forward.items()) 287 | entities[category] = (forward, reverse) 288 | 289 | def parseEntity(match): 290 | entity = match.group(1) 291 | try: 292 | if entity.isdigit(): 293 | return reverse[int(entity)] 294 | else: 295 | return chr(forward[entity]) 296 | except: 297 | return match.group(0) 298 | xml = re.sub('&([a-zA-Z0-9]+);', parseEntity, xml) 299 | return xml 300 | 301 | 302 | # def extract(tar_path, target_path, mode='r:gz'): 303 | # try: 304 | # tar = tarfile.open(tar_path, mode) 305 | # tar.extractall(target_path) 306 | # tar.close() 307 | # return True 308 | # except Exception as e: 309 | # print('Extract fail ' + e.__class__.__name__) 310 | # return False 311 | 312 | # Don't catch error 313 | def extract(tar_path, target_path, mode='r:gz'): 314 | tar = tarfile.open(tar_path, mode) 315 | tar.extractall(target_path) 316 | tar.close() 317 | return True 318 | 319 | def uninstallLanguage(languageWithVersion): 320 | languageForPath = getLanguageSlug(languageWithVersion) 321 | print('Uninstall languageWithVersion ' + languageWithVersion) 322 | language_path = getDocsPath(True) + "/" + languageForPath 323 | if os.path.isdir(language_path): 324 | shutil.rmtree(language_path) 325 | if installed_languages.get(languageForPath) != None: 326 | installed_languages.pop(languageForPath) 327 | if languages_index.get(languageWithVersion) != None: 328 | languages_index.pop(languageWithVersion) 329 | saveInstalledLanguages() 330 | 331 | 332 | def installLanguage(languageWithVersion): 333 | if not languageWithVersion: 334 | return False 335 | 336 | uninstallLanguage(languageWithVersion) 337 | 338 | languageForPath = getLanguageSlug(languageWithVersion) 339 | print('Install languageWithVersion ' + languageWithVersion) 340 | 341 | err = None 342 | try: 343 | url = 'http://dl.devdocs.io/' + languageForPath + '.tar.gz' 344 | user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36' 345 | print('Downloading ' + url) 346 | req = urllib.request.Request(url) 347 | req.add_header('User-Agent', user_agent) 348 | 349 | filename = getDocsPath(True) + '/' + \ 350 | languageForPath + '.tar.gz.downloading' 351 | http_proxy = getSetting('http_proxy') 352 | if http_proxy: 353 | proxy_handler = urllib.request.ProxyHandler({'http': http_proxy}) 354 | # proxy_auth_handler = urllib.request.ProxyBasicAuthHandler() 355 | # proxy_auth_handler.add_password('realm', 'host', 'username', 'password') 356 | 357 | opener = urllib.request.build_opener(proxy_handler) 358 | response = opener.open(req) 359 | else: 360 | response = urllib.request.urlopen(req) 361 | try: 362 | # assume correct header 363 | totalsize = int(response.headers['Content-Length']) 364 | except NameError: 365 | totalsize = None 366 | except KeyError: 367 | totalsize = None 368 | 369 | outputfile = open(filename, 'wb') 370 | 371 | readsofar = 0 372 | chunksize = 8192 373 | try: 374 | while(True): 375 | # download chunk 376 | data = response.read(chunksize) 377 | if not data: # finished downloading 378 | break 379 | readsofar += len(data) 380 | outputfile.write(data) # save to filename 381 | if totalsize: 382 | # report progress 383 | percent = readsofar * 1e2 / totalsize # assume totalsize > 0 384 | sublime.status_message( 385 | package_name + ': %.0f%% downloading %s' % (percent, languageForPath,)) 386 | else: 387 | kb = readsofar / 1024 388 | sublime.status_message( 389 | package_name + ': %.0f KB downloading %s' % (kb, languageForPath,)) 390 | finally: 391 | outputfile.close() 392 | if totalsize and readsofar != totalsize: 393 | os.unlink(filename) 394 | err = 'Download failed' 395 | 396 | except (urllib.error.HTTPError) as e: 397 | err = '%s: HTTP error %s contacting API' % (__name__, str(e.code)) 398 | except (urllib.error.URLError) as e: 399 | err = '%s: URL error %s contacting API' % (__name__, str(e.reason)) 400 | except Exception as e: 401 | err = e.__class__.__name__ 402 | 403 | print("Download success") 404 | 405 | if not err: 406 | newname = getDocsPath(True) + '/' + languageForPath + '.tar.gz' 407 | if os.path.isfile(newname): 408 | os.unlink(newname) 409 | os.rename(filename, newname) 410 | print("Extract " + newname) 411 | if extract(newname, getDocsPath(True) + '/' + languageForPath): 412 | global installed_languages 413 | installed_languages[languageForPath] = { 414 | "mtime": time.time(), 415 | "name": languageWithVersion, 416 | "slug": languageForPath 417 | } 418 | os.unlink(newname) 419 | saveInstalledLanguages() 420 | return True 421 | else: 422 | err = 'Extract file error' 423 | 424 | print(err) 425 | sublime.message_dialog('LanguageVersion ' + languageWithVersion + 426 | ' install failed. Please try again.') 427 | return False 428 | 429 | 430 | class DevdocsShowDefinitionCommand(sublime_plugin.TextCommand): 431 | match_languages = None 432 | 433 | def want_event(self): 434 | return True 435 | 436 | def run(self, edit, event=None, symbol=None): 437 | language, language_type = parseViewLanguage(self.view) 438 | print("Current view language:" + language) 439 | if not isInstalled(language, True): 440 | self.view.run_command("devdocs_set_default_version") 441 | return False 442 | if symbol == None: 443 | if event: 444 | pt = self.view.window_to_text((event["x"], event["y"])) 445 | else: 446 | pt = self.view.sel()[0] 447 | symbol, locations = sublime_symbol.symbol_at_point( 448 | self.view, pt) 449 | print("Looking for symbol " + symbol + " in " + language) 450 | symbolInfo = getSymbolInIndex(symbol, language) 451 | if not symbolInfo: 452 | print("Not found the symbol " + symbol) 453 | return 454 | print("Found symbol") 455 | print(symbolInfo) 456 | self.show_popup( 457 | symbol, getSymbolDescriptionFromHtml(symbolInfo['path'], language)) 458 | 459 | def show_popup(self, symbol, symbolDescription): 460 | global popup_default_max_height, popup_default_max_width 461 | output = symbolDescription 462 | 463 | # if getSetting('debug'): 464 | # print(output) 465 | 466 | width, height = self.view.viewport_extent() 467 | output = self.formatPopup(output, symbol=symbol) 468 | 469 | # It seems sublime will core when the output is too long 470 | # In some cases the value can set to 76200, but we use a 65535 for 471 | # safety. 472 | output = output[:65535] 473 | 474 | self.view.show_popup( 475 | output, 476 | # flags=sublime.COOPERATE_WITH_AUTO_COMPLETE | sublime.HTML, 477 | flags=sublime.COOPERATE_WITH_AUTO_COMPLETE, 478 | location=-1, 479 | max_width=min(getSetting("popup_max_width", 480 | popup_default_max_width), width), 481 | max_height=min(getSetting("popup_max_height", 482 | popup_default_max_height), height - 100), 483 | on_navigate=self.on_navigate, 484 | on_hide=self.on_hide 485 | ) 486 | 487 | def on_hide(self): 488 | self.currentSymbol = '' 489 | self.history = [] 490 | 491 | def on_navigate(self, url): 492 | if re.search('^https?://', url): 493 | webbrowser.open_new(url) 494 | return True 495 | 496 | # m = re.search('^(changeto|constant)\.(.*)', url) 497 | # if m: 498 | # if m.group(1) == 'changeto': 499 | # symbol, content = getSymbolDescription( 500 | # self.currentSymbol, m.group(2)) 501 | # else: 502 | # self.view.run_command('docphp_insert', {"string": m.group(2)}) 503 | # self.view.hide_popup() 504 | 505 | # elif url == 'history.back': 506 | # symbol = self.history.pop() 507 | # self.currentSymbol = symbol 508 | # else: 509 | # self.history.append(self.currentSymbol) 510 | # symbol = url[:url.find('.html')] 511 | # self.currentSymbol = symbol 512 | # symbol, content = getSymbolDescription(symbol) 513 | 514 | # if content == False: 515 | # return False 516 | 517 | # content = self.formatPopup( 518 | # content, symbol=symbol, can_back=len(self.history) > 0) 519 | 520 | # content = content[:65535] 521 | # self.view.update_popup(content) 522 | 523 | def formatPopup(self, content, symbol, can_back=False): 524 | if not isinstance(content, str): 525 | return 526 | 527 | content = decodeEntity(content) 528 | # content = decodeEntity(content, 'html') 529 | # return content 530 | 531 | parser = PopupHTMLParser(symbol, can_back) 532 | try: 533 | parser.feed(content) 534 | except FinishError: 535 | pass 536 | content = parser.output 537 | # content = '
' + \ 539 | # content + "
" 540 | if getSetting("use_style"): 541 | print("Use custom style") 542 | content = '
' + content + "
" 544 | content = re.sub('([A-Z_]+)', 545 | '\\1', content) 546 | # print(content) 547 | return content 548 | 549 | 550 | class DevdocsSearchSymbolCommand(sublime_plugin.TextCommand): 551 | allSymbol = None 552 | 553 | def run(self, edit): 554 | language, language_type = parseViewLanguage(self.view) 555 | allSymbol = getAllSymbol(language) 556 | self.allSymbol = allSymbol 557 | print(allSymbol) 558 | sublime.Window.show_quick_panel( 559 | sublime.active_window(), 560 | allSymbol, 561 | on_select=self.on_select 562 | ) 563 | 564 | def on_select(self, selectKey): 565 | if selectKey == -1: 566 | return False 567 | self.view.run_command("devdocs_show_definition", { 568 | "symbol": self.allSymbol[selectKey]}) 569 | 570 | 571 | class DevdocsSetDefaultVersion(sublime_plugin.TextCommand): 572 | matchResult = None 573 | selected_language_type = None 574 | selected_language_version = None 575 | 576 | def run(self, edit): 577 | language, language_type = parseViewLanguage(self.view) 578 | matchResult = searchInAllLanguages(language_type, 'set_as_default') 579 | 580 | self.matchResult = matchResult 581 | print(matchResult) 582 | sublime.Window.show_quick_panel( 583 | sublime.active_window(), 584 | matchResult, 585 | on_select=self.on_select 586 | ) 587 | 588 | def on_select(self, selectKey): 589 | if selectKey == -1: 590 | return False 591 | language, language_type = parseViewLanguage(self.view) 592 | selected_value = self.matchResult[selectKey] 593 | print('Selected ' + selected_value[0]) 594 | if selected_value[1] == installed_tip['set_as_default']: 595 | setLanguageDefaultVersion(language_type, selected_value[0]) 596 | else: 597 | self.selected_language_type = language_type 598 | self.selected_language_version = selected_value[0] 599 | sublime.set_timeout_async(self.installLanguageAndSetAsDefault, 0) 600 | 601 | def installLanguageAndSetAsDefault(self): 602 | if not self.selected_language_version or not self.selected_language_type: 603 | return False 604 | if installLanguage(self.selected_language_version): 605 | setLanguageDefaultVersion( 606 | self.selected_language_type, self.selected_language_version) 607 | 608 | 609 | class DevdocsSetSyntaxAlias(sublime_plugin.TextCommand): 610 | all_languages_distinct = None 611 | selected_language_version = None 612 | 613 | def run(self, edit): 614 | all_languages_distinct = self.getAllLanguagesDistinct() 615 | self.all_languages_distinct = all_languages_distinct 616 | print(all_languages_distinct) 617 | sublime.Window.show_quick_panel( 618 | sublime.active_window(), 619 | all_languages_distinct, 620 | on_select=self.on_select 621 | ) 622 | 623 | def getAllLanguagesDistinct(self): 624 | if self.all_languages_distinct == None: 625 | self.all_languages_distinct = [] 626 | tmp_map = {} 627 | languages = getAllLanguages() 628 | for key, language in enumerate(languages): 629 | languageName = language.split("@", 1)[0] 630 | if not tmp_map.get(languageName): 631 | self.all_languages_distinct.append( 632 | [languageName, "Set now syntax alias this language"]) 633 | tmp_map[languageName] = True 634 | 635 | return self.all_languages_distinct 636 | 637 | def on_select(self, selectKey): 638 | if selectKey == -1: 639 | return False 640 | language = self.all_languages_distinct[selectKey] 641 | print('Selected ' + language[0]) 642 | setSyntaxAlias(self.view.settings().get('syntax'), language[0]) 643 | 644 | 645 | class DevdocsShowAllLanguages(sublime_plugin.TextCommand): 646 | all_languages_display = None 647 | selected_language_version = None 648 | 649 | def run(self, edit): 650 | all_languages_display = checkAllLanguagesForDisplay() 651 | self.all_languages_display = all_languages_display 652 | print(all_languages_display) 653 | sublime.Window.show_quick_panel( 654 | sublime.active_window(), 655 | all_languages_display, 656 | on_select=self.on_select 657 | ) 658 | 659 | def on_select(self, selectKey): 660 | if selectKey == -1: 661 | return False 662 | language = self.all_languages_display[selectKey] 663 | print('Selected ' + language[0]) 664 | if language[1] == installed_tip['toggle']: 665 | uninstallLanguage(language[0]) 666 | else: 667 | self.selected_language_version = language[0] 668 | sublime.set_timeout_async(self.installLanguage, 0) 669 | 670 | def installLanguage(self): 671 | installLanguage(self.selected_language_version) 672 | 673 | 674 | class PopupHTMLParser(HTMLParser): 675 | symbol = '' 676 | can_back = False 677 | stack = [] 678 | output = '' 679 | as_div = ['blockquote', 'tr', 'li', 'ul', 'dl', 680 | 'dt', 'dd', 'table', 'tbody', 'thead'] 681 | strip = ['td'] 682 | started = False 683 | 684 | def __init__(self, symbol, can_back): 685 | self.symbol = symbol 686 | self.can_back = can_back 687 | super().__init__() 688 | 689 | def parseAttrs(self, attrs): 690 | ret = {} 691 | for k, v in attrs: 692 | ret[k] = v 693 | return ret 694 | 695 | def handle_starttag(self, tag, attrs): 696 | attrs = self.parseAttrs(attrs) 697 | 698 | for k in attrs: 699 | v = attrs[k] 700 | if k == 'id' and v == self.symbol: 701 | self.output = '' 702 | if k == 'class' and v == 'up': 703 | self.output = '' 704 | 705 | if tag in self.as_div: 706 | if 'class' in attrs: 707 | attrs['class'] += ' ' + tag 708 | else: 709 | attrs['class'] = tag 710 | tag = 'div' 711 | if tag in self.strip: 712 | return 713 | 714 | self.stack.append({'tag': tag, 'attrs': attrs}) 715 | border = self.shall_border(tag, attrs) 716 | if border: 717 | self.output += '
' 718 | self.output += self.get_tag_text(tag, attrs) 719 | 720 | def handle_endtag(self, tag): 721 | if tag in self.as_div: 722 | tag = 'div' 723 | if tag in self.strip: 724 | return 725 | try: 726 | while(True): 727 | previous = self.stack.pop() 728 | self.output += '' 729 | 730 | # if re.search('h[1-6]', tag): 731 | # self.output += '
' 732 | 733 | if self.shall_border(previous['tag'], previous['attrs']): 734 | self.output += '
' 735 | for k in previous['attrs']: 736 | v = previous['attrs'][k] 737 | if k == 'id' and v == self.symbol: 738 | pass 739 | # raise FinishError 740 | if k == 'class' and v == 'up': 741 | self.navigate_up = self.output 742 | if tag == previous['tag']: 743 | break 744 | 745 | except IndexError: 746 | pass 747 | 748 | def handle_startendtag(self, tag, attrs): 749 | if tag in self.as_div: 750 | if 'class' in attrs: 751 | attrs['class'] += ' ' + tag 752 | else: 753 | attrs['class'] = tag 754 | tag = 'div' 755 | self.output += self.get_tag_text(tag, attrs, True) 756 | 757 | def handle_data(self, data): 758 | self.output += data 759 | pass 760 | 761 | def handle_entityref(self, name): 762 | self.output += '&' + name + ';' 763 | 764 | def handle_charref(self, name): 765 | self.output += '&' + name + ';' 766 | 767 | def shall_border(self, tag, attrs): 768 | if tag.lower() not in ['div', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']: 769 | return False 770 | for k in attrs: 771 | v = attrs[k] 772 | if k == 'class': 773 | if re.search('\\b(phpcode|classsynopsis|methodsynopsis|note|informaltable)\\b', v): 774 | return 'gray' 775 | elif re.search('\\b(tip)\\b', v): 776 | return 'blue' 777 | elif re.search('\\b(warning)\\b', v): 778 | return 'pink' 779 | elif re.search('\\b(caution)\\b', v): 780 | return 'yellow' 781 | return False 782 | 783 | def get_tag_text(self, tag, attrs, is_startend=False): 784 | return '<' + (tag + ' ' + ' '.join(map(lambda m: m + '="' + re.sub('(?' if is_startend else '>') 785 | 786 | 787 | class FinishError(Exception): 788 | 789 | """For stopping the HTMLParser""" 790 | pass 791 | --------------------------------------------------------------------------------