├── .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 = '
([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 += '