├── .gitignore ├── LICENSE ├── README ├── configs ├── babel.json ├── click.json ├── flask-sqlalchemy.json ├── flask.json ├── jinja.json ├── platter.json └── werkzeug.json ├── docbuilder.py ├── nginx.conf ├── setup.py └── themes ├── babel ├── search.html ├── sidebarintro.html ├── sidebarlogo.html ├── static │ └── babel.css └── theme.conf ├── click ├── search.html ├── sidebarintro.html ├── sidebarlogo.html ├── static │ └── click.css └── theme.conf ├── flask-sqlalchemy ├── sidebarintro.html ├── sidebarlogo.html ├── static │ └── flask-sqlalchemy.css └── theme.conf ├── flask ├── search.html ├── sidebarintro.html ├── sidebarlogo.html ├── static │ └── flask.css └── theme.conf ├── jinja ├── search.html ├── sidebarintro.html ├── sidebarlogo.html ├── static │ └── jinja.css └── theme.conf ├── jinja_theme_support.py ├── platter ├── search.html ├── sidebarintro.html ├── sidebarlogo.html ├── static │ └── platter.css └── theme.conf ├── pocoo ├── 404.html ├── customsearch.html ├── layout.html ├── relations.html ├── searchbox.html ├── sidebarversions.html ├── static │ ├── pocoo.css_t │ └── small.css └── theme.conf ├── pocoo_theme_support.py └── werkzeug ├── search.html ├── sidebarintro.html ├── sidebarlogo.html ├── static └── werkzeug.css └── theme.conf /.gitignore: -------------------------------------------------------------------------------- 1 | checkouts 2 | build 3 | .DS_Store 4 | *.egg-info 5 | *.pyc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 by Armin Ronacher. 2 | 3 | Some rights reserved. 4 | 5 | Redistribution and use in source and binary forms of the theme, with or 6 | without modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following 14 | disclaimer in the documentation and/or other materials provided 15 | with the distribution. 16 | 17 | * The names of the contributors may not be used to endorse or 18 | promote products derived from this software without specific 19 | prior written permission. 20 | 21 | We kindly ask you to only use these themes in an unmodified manner just 22 | for Flask and Flask-related products, not for unrelated projects. If you 23 | like the visual style and want to use it for your own projects, please 24 | consider making some larger changes to the themes (such as changing 25 | font faces, sizes, colors or margins). 26 | 27 | THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 | ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE 37 | POSSIBILITY OF SUCH DAMAGE. 38 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Flask Documentation 2 | =================== 3 | 4 | No longer used. The docs are now built and hosted with Read the Docs. 5 | The Sphinx themes are at https://github.com/pallets/pallets-sphinx-themes. 6 | 7 | This repository contains sphinx styles for Flask and Flask related 8 | projects and a wrapper script to build the online documentation. 9 | 10 | How to build the docs (for instance Flask): 11 | 12 | $ pip install --editable . 13 | $ flask-docbuilder build --config configs/flask.json 14 | 15 | Note that the master branch is built by the pocoo build server. 16 | Changes here might break the build so please be careful. 17 | 18 | How it works in general: 19 | 20 | * themes are shared and live in the `themes` folder. 21 | * configs about how the per-project docs are structured live in 22 | the `configs` folder. 23 | * the build server runs `flask-docbuilder build-all` to generate 24 | all documentation and stores it on the pocoo server. 25 | -------------------------------------------------------------------------------- /configs/babel.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "babel", 3 | "name": "Babel", 4 | "doc_path": "./docs", 5 | "pygments_style": "tango", 6 | "sidebars": { 7 | "index": ["sidebarintro.html", "sidebarversions.html", 8 | "searchbox.html"], 9 | "**": ["sidebarlogo.html", "localtoc.html", "sidebarversions.html", 10 | "relations.html", "searchbox.html"] 11 | }, 12 | "theme": "babel", 13 | "theme_path": "../themes", 14 | "versions": [ 15 | { 16 | "slug": "dev", 17 | "type": "unstable", 18 | "title": "Development", 19 | "note": "unstable", 20 | "version": "3.0-dev", 21 | "repo": "https://github.com/python-babel/babel@master", 22 | "warning": "This is the documentation for the development version of Babel" 23 | }, 24 | { 25 | "slug": "2", 26 | "type": "stable", 27 | "title": "Babel 2.x", 28 | "note": "stable", 29 | "version": "2.0", 30 | "repo": "https://github.com/python-babel/babel@2.x-maintenance" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /configs/click.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "click", 3 | "name": "Click", 4 | "doc_path": "./docs", 5 | "pygments_style": "tango", 6 | "sidebars": { 7 | "index": ["sidebarintro.html", "sidebarversions.html", 8 | "searchbox.html"], 9 | "**": ["sidebarlogo.html", "localtoc.html", "sidebarversions.html", 10 | "relations.html", "searchbox.html"] 11 | }, 12 | "theme": "click", 13 | "theme_path": "../themes", 14 | "versions": [ 15 | { 16 | "slug": "dev", 17 | "type": "unstable", 18 | "title": "Development", 19 | "note": "unstable", 20 | "version": "7.0-dev", 21 | "repo": "https://github.com/mitsuhiko/click@master", 22 | "warning": "This is the documentation for the development version of Click" 23 | }, 24 | { 25 | "slug": "6", 26 | "type": "stable", 27 | "title": "Click 6.x", 28 | "note": "stable", 29 | "version": "6.0", 30 | "repo": "https://github.com/mitsuhiko/click@6.x-maintenance" 31 | }, 32 | { 33 | "slug": "5", 34 | "type": "stable", 35 | "title": "Click 5.x", 36 | "note": "stable", 37 | "version": "5.0", 38 | "repo": "https://github.com/mitsuhiko/click@5.x-maintenance" 39 | }, 40 | { 41 | "slug": "4", 42 | "title": "Click 4.x", 43 | "version": "4.0", 44 | "repo": "https://github.com/mitsuhiko/click@4.x-maintenance" 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /configs/flask-sqlalchemy.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "flask-sqlalchemy", 3 | "name": "Flask-SQLAlchemy", 4 | "doc_path": "./docs", 5 | "sidebars": { 6 | "index": [ 7 | "sidebarlogo.html", 8 | "sidebarintro.html", 9 | "sidebarversions.html", 10 | "searchbox.html" 11 | ], 12 | "**": [ 13 | "sidebarlogo.html", 14 | "localtoc.html", 15 | "sidebarversions.html", 16 | "relations.html", 17 | "searchbox.html" 18 | ] 19 | }, 20 | "theme": "flask-sqlalchemy", 21 | "theme_path": "../themes", 22 | "versions": [ 23 | { 24 | "slug": "dev", 25 | "type": "unstable", 26 | "title": "Development", 27 | "version": "3.0-dev", 28 | "repo": "https://github.com/mitsuhiko/flask-sqlalchemy@master", 29 | "warning": "This is the documentation for the development version of Flask-SQLAlchemy" 30 | }, 31 | { 32 | "slug": "2.3", 33 | "type": "stable", 34 | "title": "2.3.1", 35 | "note": "stable", 36 | "version": "2.3.1", 37 | "repo": "https://github.com/mitsuhiko/flask-sqlalchemy@2.3.1" 38 | }, 39 | { 40 | "slug": "2.2", 41 | "title": "2.2.0", 42 | "version": "2.2", 43 | "repo": "https://github.com/mitsuhiko/flask-sqlalchemy@2.2" 44 | }, 45 | { 46 | "slug": "2.1", 47 | "title": "2.1.0", 48 | "version": "2.1", 49 | "repo": "https://github.com/mitsuhiko/flask-sqlalchemy@2.1" 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /configs/flask.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "flask", 3 | "name": "Flask", 4 | "doc_path": "./docs", 5 | "default_url_prefix": "/docs", 6 | "new_theme": true, 7 | "pre_build_steps": [ 8 | "pip install -U sphinx sphinxcontrib-log-cabinet pallets-sphinx-themes" 9 | ], 10 | "sidebars": { 11 | "index": ["sidebarintro.html", "sidebarversions.html", "searchbox.html"], 12 | "**": ["sidebarlogo.html", "localtoc.html", "sidebarversions.html", 13 | "relations.html", "searchbox.html"] 14 | }, 15 | "theme": "flask", 16 | "theme_path": "../themes", 17 | "versions": [ 18 | { 19 | "slug": "dev", 20 | "type": "unstable", 21 | "title": "Development", 22 | "note": "unstable", 23 | "version": "1.1.dev", 24 | "repo": "https://github.com/pallets/flask@master" 25 | }, 26 | { 27 | "slug": "1.0", 28 | "type": "stable", 29 | "title": "Flask 1.0", 30 | "note": "stable", 31 | "version": "1.0.2", 32 | "repo": "https://github.com/pallets/flask@1.0-maintenance" 33 | }, 34 | { 35 | "slug": "0.12", 36 | "title": "Flask 0.12", 37 | "note": null, 38 | "version": "0.12.4", 39 | "repo": "https://github.com/pallets/flask@0.12-maintenance" 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /configs/jinja.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "jinja", 3 | "name": "Jinja2", 4 | "doc_path": "./docs", 5 | "default_url_prefix": "/docs", 6 | "pygments_style": "jinja_theme_support.JinjaStyle", 7 | "sidebars": { 8 | "index": ["sidebarlogo.html", "sidebarintro.html", "sidebarversions.html", 9 | "searchbox.html"], 10 | "**": ["sidebarlogo.html", "localtoc.html", "sidebarversions.html", 11 | "relations.html", "searchbox.html"] 12 | }, 13 | "theme": "jinja", 14 | "theme_path": "../themes", 15 | "versions": [ 16 | { 17 | "slug": "dev", 18 | "type": "unstable", 19 | "title": "Development", 20 | "note": "unstable", 21 | "version": "2.11.dev", 22 | "repo": "https://github.com/pallets/jinja@master", 23 | "warning": "This is the documentation for the development version of Jinja2" 24 | }, 25 | { 26 | "slug": "2.10", 27 | "type": "stable", 28 | "title": "Jinja 2.10.x", 29 | "note": "stable", 30 | "version": "2.10", 31 | "repo": "https://github.com/pallets/jinja@2.10" 32 | }, 33 | { 34 | "slug": "2.9", 35 | "title": "Jinja 2.9.x", 36 | "note": null, 37 | "version": "2.9", 38 | "repo": "https://github.com/pallets/jinja2@2.9.6" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /configs/platter.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "platter", 3 | "name": "Platter", 4 | "doc_path": "./docs", 5 | "pygments_style": "tango", 6 | "sidebars": { 7 | "index": ["sidebarintro.html", "sidebarversions.html", 8 | "searchbox.html"], 9 | "**": ["sidebarlogo.html", "localtoc.html", "sidebarversions.html", 10 | "relations.html", "searchbox.html"] 11 | }, 12 | "theme": "platter", 13 | "theme_path": "../themes", 14 | "versions": [ 15 | { 16 | "slug": "dev", 17 | "type": "unstable", 18 | "title": "Development", 19 | "note": "unstable", 20 | "version": "1.0-dev", 21 | "repo": "https://github.com/mitsuhiko/platter@master", 22 | "warning": "This is the documentation for the development version of Platter" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /configs/werkzeug.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "werkzeug", 3 | "name": "Werkzeug", 4 | "doc_path": "./docs", 5 | "default_url_prefix": "/docs", 6 | "sidebars": { 7 | "index": ["sidebarlogo.html", "sidebarintro.html", "sidebarversions.html", 8 | "searchbox.html"], 9 | "**": ["sidebarlogo.html", "localtoc.html", "sidebarversions.html", 10 | "relations.html", "searchbox.html"] 11 | }, 12 | "theme": "werkzeug", 13 | "theme_path": "../themes", 14 | "versions": [ 15 | { 16 | "slug": "dev", 17 | "type": "unstable", 18 | "title": "Development", 19 | "note": "unstable", 20 | "version": "0.14-dev", 21 | "repo": "https://github.com/mitsuhiko/werkzeug@master", 22 | "warning": "This is the documentation for the development version of Werkzeug" 23 | }, 24 | { 25 | "slug": "0.14", 26 | "type": "stable", 27 | "title": "Werkzeug 0.14.x", 28 | "note": "stable", 29 | "version": "0.14.1", 30 | "repo": "https://github.com/mitsuhiko/werkzeug@0.14.1" 31 | }, 32 | { 33 | "slug": "0.13", 34 | "title": "Werkzeug 0.13.x", 35 | "version": "0.13", 36 | "repo": "https://github.com/mitsuhiko/werkzeug@0.13" 37 | }, 38 | { 39 | "slug": "0.12", 40 | "title": "Werkzeug 0.12.x", 41 | "version": "0.12.2", 42 | "repo": "https://github.com/mitsuhiko/werkzeug@0.12.2" 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /docbuilder.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import json 4 | import shutil 5 | import tempfile 6 | import subprocess 7 | 8 | import click 9 | 10 | 11 | config_override_template = '''\ 12 | new_theme = %(new_theme)s 13 | 14 | import os 15 | import sys 16 | 17 | if not new_theme: 18 | sys.path.insert(0, %(theme_path)r) 19 | #__import__('pocoo_theme_support') 20 | 21 | sys.path[:] = [os.path.abspath(x) for x in sys.path] 22 | 23 | # Some defaults 24 | html_static_path = [] 25 | html_favicon = None 26 | html_logo = None 27 | latex_additional_files = [] 28 | latex_logo = None 29 | 30 | # Source the old file and ensure the paths are setup correctly afterwards 31 | _old_file = __file__ 32 | __file__ = 'conf.py' 33 | _here = os.getcwd() 34 | _real_path = %(real_path)r 35 | os.chdir(_real_path) 36 | 37 | with open('conf.py', 'rb') as f: 38 | code = compile(f.read(), 'conf.py', 'exec') 39 | exec(code, globals()) 40 | 41 | sys.path[:] = [os.path.abspath(x) for x in sys.path] 42 | os.chdir(_here) 43 | 44 | 45 | def fix_path(x): 46 | if x: 47 | return os.path.join(_real_path, x) 48 | 49 | 50 | html_static_path = [fix_path(_x) for _x in html_static_path] 51 | latex_additional_files = [fix_path(_x) for _x in latex_additional_files] 52 | __file__ = _old_file 53 | 54 | if not new_theme: 55 | html_additional_pages = dict(globals().get('html_additional_pages') or {}) 56 | html_additional_pages['404'] = '404.html' 57 | 58 | html_favicon = fix_path(html_favicon) 59 | html_logo = fix_path(html_logo) 60 | latex_logo = fix_path(latex_logo) 61 | 62 | release = %(release)r 63 | version = %(version)r 64 | 65 | # Overrides 66 | if not new_theme: 67 | html_favicon = None 68 | project = %(project)r 69 | 70 | templates_path = [] 71 | html_title = '%%s Documentation (%%s)' %% (project, version) 72 | html_theme = %(theme)r 73 | html_theme_options = {} 74 | html_theme_path = [%(theme_path)r] 75 | html_sidebars = %(sidebars)r 76 | 77 | pygments_style = %(pygments_style)r 78 | 79 | html_context = dict(globals().get('html_context') or {}) 80 | html_context.update(%(context_vars)r) 81 | ''' 82 | 83 | build_script = '''\ 84 | #!/bin/bash 85 | . %(venv_path)s/bin/activate 86 | 87 | pip install --upgrade Sphinx 88 | 89 | export PYTHONPATH="%(checkout_path)s:$PYTHONPATH" 90 | 91 | cd %(checkout_path)s 92 | pip install --editable . 93 | git submodule update --init 94 | 95 | %(build_steps)s 96 | 97 | cd %(doc_source_path)s 98 | 99 | sphinx-build \\ 100 | -d %(doc_source_path)s/.doctrees \\ 101 | -b dirhtml -c "%(config_path)s" -T . "%(output_path)s" 102 | 103 | #sphinx-build \\ 104 | # -d %(doc_source_path)s/.doctrees \\ 105 | # -b json -c "%(config_path)s" -T . "%(output_path)s" 106 | 107 | #sphinx-build \\ 108 | # -d %(doc_source_path)s/.doctrees \\ 109 | # -b latex -c "%(config_path)s" -T . "%(output_path)s/.latex" 110 | 111 | #(cd %(output_path)s/.latex; make all-pdf) 112 | ''' 113 | 114 | 115 | def build_context_vars(this_version, config): 116 | versions = [] 117 | warning = None 118 | config_new_theme = config.get('new_theme') 119 | current_new_theme = None 120 | 121 | for version in config['versions']: 122 | is_current = this_version == version['slug'] 123 | versions.append({ 124 | 'slug': version['slug'], 125 | 'title': version['title'], 126 | 'note': version.get('note'), 127 | 'is_current': is_current, 128 | }) 129 | if is_current: 130 | warning = version.get('warning') 131 | current_new_theme = version.get('new_theme') 132 | 133 | if config_new_theme or current_new_theme: 134 | return { 135 | 'versions': versions, 136 | } 137 | 138 | return { 139 | 'documentation_versions': versions, 140 | 'documentation_version_warning': warning, 141 | } 142 | 143 | 144 | def ensure_checkout(checkout_folder, repo_url): 145 | try: 146 | os.makedirs(checkout_folder) 147 | except OSError: 148 | pass 149 | 150 | client = None 151 | url, branch = repo_url.rsplit('@', 1) 152 | try: 153 | if os.path.isdir(os.path.join(checkout_folder, '.git')): 154 | client = subprocess.Popen([ 155 | 'git', 'fetch', 'origin', 156 | '%s:%s' % (branch, branch), 157 | '--update-head-ok', 158 | ], cwd=checkout_folder) 159 | client.wait() 160 | client = subprocess.Popen([ 161 | 'git', 'reset', '--hard', 162 | ], cwd=checkout_folder) 163 | client.wait() 164 | client = subprocess.Popen([ 165 | 'git', 'checkout', '--force', branch, 166 | ], cwd=checkout_folder) 167 | client.wait() 168 | else: 169 | client = subprocess.Popen([ 170 | 'git', 'clone', 171 | '--branch', branch, 172 | url, 173 | checkout_folder 174 | ]) 175 | client.wait() 176 | finally: 177 | if client is not None: 178 | try: 179 | client.kill() 180 | except OSError: 181 | pass 182 | 183 | 184 | def build_version(config, version_config, output_folder, checkout_folder): 185 | version_checkout_folder = os.path.abspath(os.path.join( 186 | checkout_folder, str('%s-%s' % (config['id'], 187 | version_config['slug'])))) 188 | venv_path = os.path.join(version_checkout_folder, '.venv') 189 | 190 | ensure_checkout(version_checkout_folder, version_config['repo']) 191 | doc_source_path = os.path.join(version_checkout_folder, 192 | str(config['doc_path'])) 193 | 194 | config_path = tempfile.mkdtemp(prefix='.versionoverlay') 195 | context_vars = build_context_vars(version_config['slug'], config) 196 | new_theme = bool( 197 | config.get('new_theme') or version_config.get('new_theme')) 198 | client = None 199 | 200 | try: 201 | if new_theme: 202 | client = subprocess.Popen(['python3.6', '-m', 'venv', venv_path]) 203 | else: 204 | client = subprocess.Popen(['virtualenv', venv_path]) 205 | client.wait() 206 | 207 | with open(os.path.join(config_path, 'conf.py'), 'w') as f: 208 | f.write(config_override_template % { 209 | 'project': config['name'], 210 | 'new_theme': new_theme, 211 | 'version': '.'.join(version_config['version'].split('.')[:2]), 212 | 'release': version_config['version'], 213 | 'real_path': doc_source_path, 214 | 'theme_path': config['theme_path'], 215 | 'theme': config.get('theme') or 'pocoo', 216 | 'pygments_style': config.get('pygments_style') 217 | or 'pocoo_theme_support.PocooStyle', 218 | 'sidebars': config.get('sidebars') or {}, 219 | 'context_vars': context_vars, 220 | } + '\n') 221 | 222 | build_script_path = os.path.join(config_path, 'build.sh') 223 | with open(build_script_path, 'w') as f: 224 | f.write(build_script % { 225 | 'venv_path': venv_path, 226 | 'checkout_path': version_checkout_folder, 227 | 'doc_source_path': doc_source_path, 228 | 'output_path': os.path.abspath(output_folder), 229 | 'config_path': config_path, 230 | 'build_steps': '\n'.join(config.get('pre_build_steps') or ()), 231 | }) 232 | 233 | client = subprocess.Popen(['bash', build_script_path]) 234 | client.wait() 235 | finally: 236 | if client is not None: 237 | try: 238 | client.kill() 239 | except OSError: 240 | pass 241 | try: 242 | shutil.rmtree(config_path) 243 | except (OSError, IOError): 244 | pass 245 | 246 | 247 | def _load_config(filename): 248 | with open(filename) as f: 249 | cfg = json.load(f) 250 | cfg['base_path'] = os.path.abspath(os.path.dirname(filename)) 251 | cfg['theme_path'] = os.path.join( 252 | cfg['base_path'], cfg.get('theme_path', './themes')) 253 | return cfg 254 | 255 | 256 | def load_config(ctx, param, filename): 257 | try: 258 | return _load_config(filename) 259 | except IOError as e: 260 | raise click.BadParameter('Could not load config: %s' % e) 261 | 262 | 263 | def iter_configs(folder): 264 | for filename in os.listdir(folder): 265 | if filename.endswith('.json'): 266 | yield _load_config(os.path.join(folder, filename)) 267 | 268 | 269 | def generate_nginx_config(config, path, url_prefix=None): 270 | if url_prefix is None: 271 | url_prefix = config.get('default_url_prefix', '/') 272 | url_prefix = url_prefix.rstrip('/') 273 | escaped_prefix = re.escape(url_prefix) 274 | 275 | try_versions = [] 276 | for version in config['versions']: 277 | t = version.get('type') 278 | if t == 'stable': 279 | try_versions.append((0, version['slug'])) 280 | elif t == 'unstable': 281 | try_versions.append((1, version['slug'])) 282 | try_versions.sort() 283 | 284 | buf = [] 285 | w = buf.append 286 | 287 | # Regular documentation versions. 288 | for version in config['versions']: 289 | w('location %s/%s {' % (url_prefix, version['slug'])) 290 | w(' alias %s/%s;' % (path, version['slug'])) 291 | w('}') 292 | w('') 293 | 294 | # Fallback blocks. This also redirects the inventories. 295 | w('location %s {' % (url_prefix or '/')) 296 | w(' rewrite ^%s/?$ %s/latest/ redirect;' % (escaped_prefix, url_prefix)) 297 | 298 | for redirect_prefix in '/latest', '': 299 | w('') 300 | # Always redirect the inventory to the development one for 301 | # intersphinx. 302 | w(' rewrite ^%s%s/objects.inv$ %s/%s/objects.inv;' % 303 | (escaped_prefix, redirect_prefix, 304 | url_prefix, try_versions[-1][1])) 305 | w(' set $doc_path XXX;') 306 | w(' if ($request_uri ~* "^%s%s(|/[^?]*?)$") {' % 307 | (escaped_prefix, redirect_prefix)) 308 | w(' set $doc_path $1;') 309 | w(' }') 310 | for _, version in try_versions: 311 | w('') 312 | w(' if (-f %s/%s$doc_path/index.html) {' % (path, version)) 313 | w(' return 302 %s/%s$doc_path;' % (url_prefix, version)) 314 | w(' }') 315 | w('}') 316 | return '\n'.join(buf) 317 | 318 | 319 | @click.group() 320 | def cli(): 321 | """A wrapper around sphinx-build.""" 322 | 323 | 324 | @cli.command() 325 | @click.option('--config', type=click.Path(), required=True, 326 | callback=load_config, 327 | help='The path to the documentation config file.') 328 | @click.option('--checkout-folder', type=click.Path(), 329 | default='checkouts') 330 | @click.option('--output', '-O', type=click.Path(), default=None, 331 | help='The path to the output folder.') 332 | def build(config, checkout_folder, output): 333 | """Builds all documentation.""" 334 | if output is None: 335 | output = 'build/%s' % str(config['id']) 336 | 337 | for version_cfg in config['versions']: 338 | build_version(config, version_cfg, 339 | os.path.join(output, str(version_cfg['slug'])), 340 | checkout_folder) 341 | 342 | 343 | @cli.command('nginx-config') 344 | @click.option('--config', type=click.Path(), required=True, 345 | callback=load_config, 346 | help='The path to the documentation config file.') 347 | @click.option('--url-prefix', default=None, 348 | help='The URL prefix for the documentation.') 349 | @click.option('--path', type=click.Path(), 350 | help='The path to the documentation on the filesystem.') 351 | def nginx_config(url_prefix, path, config): 352 | """Spits out an nginx config for the given project that is ready 353 | for inclusion. This is useful because the docs have links to the 354 | latest version of the docs but it requires webserver interaction 355 | to support that pseudo URL. 356 | """ 357 | if path is None: 358 | path = os.path.abspath('build/%s' % str(config['id'])) 359 | 360 | click.echo(generate_nginx_config(config, path, url_prefix)) 361 | 362 | 363 | @cli.command('build-all') 364 | @click.option('--config-folder', type=click.Path(), required=True, 365 | default='configs', help='The folder with the config files') 366 | @click.option('--checkout-folder', type=click.Path(), 367 | default='checkouts') 368 | @click.option('--build-folder', type=click.Path(), default='build', 369 | help='Where to place the built documentation.') 370 | def build_all(config_folder, checkout_folder, build_folder): 371 | """Builds all the documentation and places it in a folder together 372 | with the nginx configs. 373 | """ 374 | for config in iter_configs(config_folder): 375 | output = '%s/%s' % (build_folder, str(config['id'])) 376 | for version_cfg in config['versions']: 377 | build_version(config, version_cfg, 378 | os.path.join(output, str(version_cfg['slug'])), 379 | checkout_folder) 380 | 381 | nginx_cfg = generate_nginx_config(config, os.path.abspath(output)) 382 | with open(os.path.join(output, 'nginx.conf'), 'w') as f: 383 | f.write(nginx_cfg + '\n') 384 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | location /docs { 3 | alias /srv/websites/flask.pocoo.org/docs; 4 | 5 | rewrite ^/docs/?$ /docs/latest/ redirect; 6 | 7 | set $doc_path xxxx; 8 | if ($request_uri ~* "^/docs/latest(|/[^?]*?)$") { 9 | set $doc_path $1; 10 | } 11 | if (-f /srv/websites/flask.pocoo.org/docs/0.10$doc_path/index.html) { 12 | return 302 /docs/0.10$doc_path; 13 | } 14 | if (-f /srv/websites/flask.pocoo.org/docs/dev$doc_path/index.html) { 15 | return 302 /docs/dev$doc_path; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | setup( 5 | name='Flask-Docbuilder', 6 | license='BSD', 7 | author='Armin Ronacher', 8 | author_email='armin.ronacher@active-4.com', 9 | py_modules=['docbuilder'], 10 | install_requires=[ 11 | 'click>=2.0', 12 | ], 13 | classifiers=[ 14 | 'PRIVATE DO NOT UPLOAD', 15 | ], 16 | entry_points=''' 17 | [console_scripts] 18 | flask-docbuilder=docbuilder:cli 19 | ''', 20 | ) 21 | -------------------------------------------------------------------------------- /themes/babel/search.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} 2 | {% from "customsearch.html" import render_gcs, render_gcs_style %} 3 | {% set title = _('Search') %} 4 | {% block body %} 5 |

Search

6 | {{ render_gcs('012722186170730423054:niv9epa3qgi') }} 7 | {{ render_gcs_style( 8 | font_family="'Ubuntu Mono', 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'", 9 | primary_color='#5D2CD1', 10 | secondary_color='#7546E3', 11 | link_hover_color='#7546E3', 12 | highlight_color='#E8EFF0' 13 | ) }} 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /themes/babel/sidebarintro.html: -------------------------------------------------------------------------------- 1 |

About Babel

2 |

3 | Babel is an internationalization library for Python. 4 |

5 |

Useful Links

6 | 12 | -------------------------------------------------------------------------------- /themes/babel/sidebarlogo.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /themes/babel/static/babel.css: -------------------------------------------------------------------------------- 1 | @import url(pocoo.css); 2 | @import url(http://fonts.googleapis.com/css?family=Ubuntu+Mono:400,400italic,700,700italic); 3 | @import url(http://fonts.googleapis.com/css?family=Open+Sans:300,400); 4 | 5 | /* fonts */ 6 | body { font-family: 'Ubuntu Mono', 'Consolas', 'Menlo', 7 | 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'; 8 | font-size: 15px; } 9 | div.admonition p.admonition-title, div.sphinxsidebar h3, div.sphinxsidebar h4, 10 | div.sphinxsidebar input, div.body h1, div.body h2, div.body h3, div.body h4, 11 | div.body h5, div.body h6 { font-family: 'Open Sans', 'Helvetica', 'Arial', 12 | sans-serif; font-weight: 400; } 13 | div.body h1, div.body h2, div.body h3, div.body h4, 14 | div.body h5, div.body h6 { color: black; } 15 | pre, code { font-family: 'Ubuntu Mono', 'Consolas', 'Menlo', 16 | 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'; 17 | font-size: 15px; background: transparent; } 18 | pre, * pre { padding: 7px 0 7px 30px!important; 19 | margin: 15px 0!important; 20 | line-height: 1.3; } 21 | 22 | /* colors */ 23 | div.body { color: #3E4349; } 24 | a { color: #5D2CD1; } 25 | a:hover { color: #7546E3; } 26 | p.version-warning { background-color: #7546E3; } 27 | a.reference { border-bottom: 1px dotted #5D2CD1; } 28 | a.reference:hover { border-bottom: 1px solid #7546E3; } 29 | a.footnote-reference { border-bottom: 1px dotted #5D2CD1; } 30 | a.footnote-reference:hover { border-bottom: 1px solid #7546E3; } 31 | a:hover code { background-color: #eeeeee; } 32 | code.xref, a code { background-color: #E8EFF0; 33 | border-bottom: 1px solid white; } 34 | 35 | /* special elements */ 36 | div.indexwrapper h1 { 37 | text-indent: -999999px; 38 | background: url(babel.png) no-repeat center center; 39 | height: 200px; 40 | } 41 | -------------------------------------------------------------------------------- /themes/babel/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = pocoo 3 | stylesheet = babel.css 4 | -------------------------------------------------------------------------------- /themes/click/search.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} 2 | {% from "customsearch.html" import render_gcs, render_gcs_style %} 3 | {% set title = _('Search') %} 4 | {% block body %} 5 |

Search

6 | {{ render_gcs('012722186170730423054:niv9epa3qgi') }} 7 | {{ render_gcs_style( 8 | font_family="'Ubuntu Mono', 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'", 9 | primary_color='#5D2CD1', 10 | secondary_color='#7546E3', 11 | link_hover_color='#7546E3', 12 | highlight_color='#E8EFF0' 13 | ) }} 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /themes/click/sidebarintro.html: -------------------------------------------------------------------------------- 1 |

About Click

2 |

3 | Click is a command line library for Python. 4 |

5 |

Useful Links

6 | 12 | -------------------------------------------------------------------------------- /themes/click/sidebarlogo.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /themes/click/static/click.css: -------------------------------------------------------------------------------- 1 | @import url(pocoo.css); 2 | @import url(http://fonts.googleapis.com/css?family=Ubuntu+Mono:400,400italic,700,700italic); 3 | @import url(http://fonts.googleapis.com/css?family=Open+Sans:300,400); 4 | 5 | /* fonts */ 6 | body { font-family: 'Ubuntu Mono', 'Consolas', 'Menlo', 7 | 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'; 8 | font-size: 15px; } 9 | div.admonition p.admonition-title, div.sphinxsidebar h3, div.sphinxsidebar h4, 10 | div.sphinxsidebar input, div.body h1, div.body h2, div.body h3, div.body h4, 11 | div.body h5, div.body h6 { font-family: 'Open Sans', 'Helvetica', 'Arial', 12 | sans-serif; font-weight: 400; } 13 | div.body h1, div.body h2, div.body h3, div.body h4, 14 | div.body h5, div.body h6 { color: black; } 15 | pre, code { font-family: 'Ubuntu Mono', 'Consolas', 'Menlo', 16 | 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'; 17 | font-size: 15px; background: transparent; } 18 | pre, * pre { padding: 7px 0 7px 30px!important; 19 | margin: 15px 0!important; 20 | line-height: 1.3; } 21 | 22 | /* colors */ 23 | div.body { color: #3E4349; } 24 | a { color: #5D2CD1; } 25 | a:hover { color: #7546E3; } 26 | p.version-warning { background-color: #7546E3; } 27 | a.reference { border-bottom: 1px dotted #5D2CD1; } 28 | a.reference:hover { border-bottom: 1px solid #7546E3; } 29 | a.footnote-reference { border-bottom: 1px dotted #5D2CD1; } 30 | a.footnote-reference:hover { border-bottom: 1px solid #7546E3; } 31 | a:hover code { background-color: #eeeeee; } 32 | code.xref, a code { background-color: #E8EFF0; 33 | border-bottom: 1px solid white; } 34 | 35 | /* special elements */ 36 | div.indexwrapper h1 { 37 | text-indent: -999999px; 38 | background: url(click.png) no-repeat center center; 39 | height: 200px; 40 | } 41 | 42 | @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { 43 | div.indexwrapper h1 { 44 | background: url(click@2x.png) no-repeat center center; 45 | background-size: 420px 175px; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /themes/click/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = pocoo 3 | stylesheet = click.css 4 | -------------------------------------------------------------------------------- /themes/flask-sqlalchemy/sidebarintro.html: -------------------------------------------------------------------------------- 1 |

About

2 |

3 | Flask-SQLAlchemy is a SQLAlchemy extension for Flask. 4 |

5 |

Useful Links

6 | 12 | 13 | Fork me on GitHub 15 | -------------------------------------------------------------------------------- /themes/flask-sqlalchemy/sidebarlogo.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /themes/flask-sqlalchemy/static/flask-sqlalchemy.css: -------------------------------------------------------------------------------- 1 | @import url(pocoo.css); 2 | 3 | /* fonts */ 4 | body { font-family: 'Georgia', serif; } 5 | div.admonition p.admonition-title, div.sphinxsidebar h3, div.sphinxsidebar h4, 6 | div.sphinxsidebar input, div.body h1, div.body h2, div.body h3, div.body h4, 7 | div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; } 8 | pre, code { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 9 | 'Bitstream Vera Sans Mono', monospace; 10 | font-size: 0.9em; } 11 | 12 | /* colors */ 13 | div.body { color: #3E4349; } 14 | a { color: #004B6B; } 15 | a:hover { color: #6D4100; } 16 | p.version-warning { background-color: #004B6B; } 17 | a.reference { border-bottom: 1px dotted #004B6B; } 18 | a.footnote-reference { border-bottom: 1px dotted #004B6B; } 19 | a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } 20 | 21 | /* other elements */ 22 | img.floatingflask { padding: 0 0 10px 10px; float: right; } 23 | 24 | 25 | /* special elements */ 26 | div.indexwrapper h1 { 27 | text-indent: -999999px; 28 | background: url(flask-sqlalchemy-title.png) no-repeat center center; 29 | height: 120px; 30 | } 31 | 32 | /* When a higher resolution logo is available */ 33 | /*@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { 34 | div.indexwrapper h1 { 35 | background: url(flask-sqlalchemy@2x.png) no-repeat center center; 36 | background-size: 420px 175px; 37 | } 38 | } 39 | */ 40 | -------------------------------------------------------------------------------- /themes/flask-sqlalchemy/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = pocoo 3 | stylesheet = flask-sqlalchemy.css 4 | -------------------------------------------------------------------------------- /themes/flask/search.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} 2 | {% from "customsearch.html" import render_gcs, render_gcs_style %} 3 | {% set title = _('Search') %} 4 | {% block body %} 5 |

Search

6 | {{ render_gcs('012722186170730423054:xrf5bo-up3u') }} 7 | {{ render_gcs_style( 8 | font_family="'Georgia', serif", 9 | primary_color='#004B6B', 10 | link_hover_color='#6D4100', 11 | secondary_color='#336F88', 12 | highlight_color='#A4E7F5' 13 | ) }} 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /themes/flask/sidebarintro.html: -------------------------------------------------------------------------------- 1 |

About Flask

2 |

3 | Flask is a micro webdevelopment framework for Python. 4 |

5 |

Useful Links

6 | 12 | -------------------------------------------------------------------------------- /themes/flask/sidebarlogo.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /themes/flask/static/flask.css: -------------------------------------------------------------------------------- 1 | @import url(pocoo.css); 2 | 3 | /* fonts */ 4 | body { font-family: 'Georgia', serif; } 5 | div.admonition p.admonition-title, div.sphinxsidebar h3, div.sphinxsidebar h4, 6 | div.sphinxsidebar input, div.body h1, div.body h2, div.body h3, div.body h4, 7 | div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; } 8 | pre, code { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 9 | 'Bitstream Vera Sans Mono', monospace; 10 | font-size: 0.9em; } 11 | 12 | /* colors */ 13 | div.body { color: #3E4349; } 14 | a { color: #004B6B; } 15 | a:hover { color: #6D4100; } 16 | p.version-warning { background-color: #004B6B; } 17 | a.reference { border-bottom: 1px dotted #004B6B; } 18 | a.footnote-reference { border-bottom: 1px dotted #004B6B; } 19 | a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } 20 | 21 | /* other elements */ 22 | img.floatingflask { padding: 0 0 10px 10px; float: right; } 23 | -------------------------------------------------------------------------------- /themes/flask/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = pocoo 3 | stylesheet = flask.css 4 | -------------------------------------------------------------------------------- /themes/jinja/search.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} 2 | {% from "customsearch.html" import render_gcs, render_gcs_style %} 3 | {% set title = _('Search') %} 4 | {% block body %} 5 |

Search

6 | {{ render_gcs('012722186170730423054:x6ckmmrakfw') }} 7 | {{ render_gcs_style( 8 | font_family="'Georgia', serif", 9 | primary_color='#aa0000', 10 | secondary_color='#dd0000', 11 | link_hover_color='#dd0000', 12 | highlight_color='#E8EFF0' 13 | ) }} 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /themes/jinja/sidebarintro.html: -------------------------------------------------------------------------------- 1 |

About Jinja2

2 |

3 | Jinja2 is a templating engine for Python. 4 |

5 |

Useful Links

6 | 12 | -------------------------------------------------------------------------------- /themes/jinja/sidebarlogo.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /themes/jinja/static/jinja.css: -------------------------------------------------------------------------------- 1 | @import url(pocoo.css); 2 | @import url(http://fonts.googleapis.com/css?family=Crimson+Text); 3 | 4 | /* fonts */ 5 | body { font-family: 'Georgia', serif; } 6 | div.admonition p.admonition-title, div.sphinxsidebar h3, div.sphinxsidebar h4, 7 | div.sphinxsidebar input, div.body h1, div.body h2, div.body h3, div.body h4, 8 | div.body h5, div.body h6 { font-family: 'Crimson Text', 'Georgia', serif; } 9 | div.body h1, div.body h2, div.body h3, div.body h4, 10 | div.body h5, div.body h6 { color: black; } 11 | pre, code { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 12 | 'Bitstream Vera Sans Mono', monospace; 13 | font-size: 0.9em; } 14 | 15 | /* colors */ 16 | div.body { color: #3E4349; } 17 | a { color: #aa0000; } 18 | a:hover { color: #dd0000; } 19 | p.version-warning { background-color: #d40; } 20 | a.reference { border-bottom: 1px dotted #bb0000; } 21 | a.reference:hover { border-bottom: 1px solid #dd0000; } 22 | a.footnote-reference { border-bottom: 1px dotted #bb0000; } 23 | a.footnote-reference:hover { border-bottom: 1px solid #dd0000; } 24 | a:hover code { background-color: #eeeeee; } 25 | code.xref, a code { background-color: #E8EFF0; 26 | border-bottom: 1px solid white; } 27 | -------------------------------------------------------------------------------- /themes/jinja/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = pocoo 3 | stylesheet = jinja.css 4 | -------------------------------------------------------------------------------- /themes/jinja_theme_support.py: -------------------------------------------------------------------------------- 1 | from pygments.style import Style 2 | from pygments.token import Keyword, Name, Comment, String, Error, \ 3 | Number, Operator, Generic 4 | 5 | 6 | class JinjaStyle(Style): 7 | title = 'Jinja Style' 8 | default_style = "" 9 | styles = { 10 | Comment: 'italic #aaaaaa', 11 | Comment.Preproc: 'noitalic #B11414', 12 | Comment.Special: 'italic #505050', 13 | 14 | Keyword: 'bold #B80000', 15 | Keyword.Type: '#808080', 16 | 17 | Operator.Word: 'bold #B80000', 18 | 19 | Name.Builtin: '#333333', 20 | Name.Function: '#333333', 21 | Name.Class: 'bold #333333', 22 | Name.Namespace: 'bold #333333', 23 | Name.Entity: 'bold #363636', 24 | Name.Attribute: '#686868', 25 | Name.Tag: 'bold #686868', 26 | Name.Decorator: '#686868', 27 | 28 | String: '#AA891C', 29 | Number: '#444444', 30 | 31 | Generic.Heading: 'bold #000080', 32 | Generic.Subheading: 'bold #800080', 33 | Generic.Deleted: '#aa0000', 34 | Generic.Inserted: '#00aa00', 35 | Generic.Error: '#aa0000', 36 | Generic.Emph: 'italic', 37 | Generic.Strong: 'bold', 38 | Generic.Prompt: '#555555', 39 | Generic.Output: '#888888', 40 | Generic.Traceback: '#aa0000', 41 | 42 | Error: '#F00 bg:#FAA' 43 | } 44 | -------------------------------------------------------------------------------- /themes/platter/search.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} 2 | {% from "customsearch.html" import render_gcs, render_gcs_style %} 3 | {% set title = _('Search') %} 4 | {% block body %} 5 |

Search

6 | {{ render_gcs('012722186170730423054:niv9epa3qgi') }} 7 | {{ render_gcs_style( 8 | font_family="'Ubuntu Mono', 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono'", 9 | primary_color='#5D2CD1', 10 | secondary_color='#7546E3', 11 | link_hover_color='#7546E3', 12 | highlight_color='#E8EFF0' 13 | ) }} 14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /themes/platter/sidebarintro.html: -------------------------------------------------------------------------------- 1 |

About Platter

2 |

3 | Platter is a deployment helper for Python. 4 |

5 |

Useful Links

6 | 12 | -------------------------------------------------------------------------------- /themes/platter/sidebarlogo.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /themes/platter/static/platter.css: -------------------------------------------------------------------------------- 1 | @import url(pocoo.css); 2 | @import url(http://fonts.googleapis.com/css?family=Fira+Mono:400,700|Bitter:400,400italic,700); 3 | 4 | /* fonts */ 5 | body { font-family: 'Bitter', serif; font-size: 16px; } 6 | div.admonition p.admonition-title, div.sphinxsidebar h3, div.sphinxsidebar h4, 7 | div.sphinxsidebar input, div.body h1, div.body h2, div.body h3, div.body h4, 8 | div.body h5, div.body h6 { font-family: 'Bitter', sans-serif; font-weight: normal; } 9 | div.body h1, div.body h2, div.body h3, div.body h4, 10 | div.body h5, div.body h6 { color: black; } 11 | pre, code { font-family: 'Fiora Mono', monospace; 12 | font-size: 16px; background: transparent; } 13 | pre, * pre { padding: 7px 0 7px 30px!important; 14 | margin: 15px 0!important; 15 | line-height: 1.3; } 16 | 17 | /* colors */ 18 | div.body { color: #163228; margin-top: 20px; } 19 | a { color: #bca612; } 20 | a:hover { color: #95840e; } 21 | p.version-warning { background-color: #e39046; } 22 | a.reference { border-bottom: 1px dotted #d1952c; } 23 | a.reference:hover { border-bottom: 1px solid #ab7311; } 24 | a.footnote-reference { border-bottom: 1px dotted #d1952c; } 25 | a.footnote-reference:hover { border-bottom: 1px solid #ab7311; } 26 | a:hover code { background-color: #eeeeee; } 27 | code.xref, a code { background-color: #E8EFF0; 28 | border-bottom: 1px solid white; } 29 | 30 | /* special elements */ 31 | div.indexwrapper h1:after { 32 | content: ""; 33 | display: block; 34 | background: url(platter.png) no-repeat center center; 35 | background-size: cover; 36 | width: 200px; 37 | height: 200px; 38 | padding-left: 10px; 39 | padding-bottom: 10px; 40 | margin-left: 20px; 41 | float: right; 42 | } 43 | 44 | @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { 45 | div.indexwrapper h1:after { 46 | background-image: url(platter@2x.png); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /themes/platter/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = pocoo 3 | stylesheet = platter.css 4 | -------------------------------------------------------------------------------- /themes/pocoo/404.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} 2 | {% set title = _('Page not Found') %} 3 | {% block body %} 4 | 5 |

Page Not Found

6 |

7 | The page you requested does not exist. Maybe you followed a bad link or 8 | the resource was removed. 9 |

10 | Maybe the documentation overview 11 | might be able to help you. 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /themes/pocoo/customsearch.html: -------------------------------------------------------------------------------- 1 | {% macro render_gcs(cx) %} 2 |

3 | 19 | 20 |
21 | 22 |
23 |
24 |
25 |
26 | 28 |
29 |
30 |
31 |
32 |
33 | {% endmacro %} 34 | 35 | {% macro render_gcs_style(font_family='serif', font_size='17px', primary_color='blue', 36 | secondary_color='#336F88', highlight_color='#FCCA46', 37 | highlight_text_color='#444', link_hover_color='green') %} 38 | 94 | {% endmacro %} 95 | -------------------------------------------------------------------------------- /themes/pocoo/layout.html: -------------------------------------------------------------------------------- 1 | {%- extends "basic/layout.html" %} 2 | {%- block extrahead %} 3 | {{ super() }} 4 | {% if pagename.endswith('/index') %} 5 | {% set href = pagename[:-5] %} 6 | {% elif pagename == 'index' %} 7 | {% set href = '' %} 8 | {% else %} 9 | {% set href = pagename + '/' %} 10 | {% endif %} 11 | 12 | 14 | {% endblock %} 15 | {%- block relbar2 %}{% endblock %} 16 | {% block header %} 17 | {{ super() }} 18 | {% if pagename == 'index' %} 19 |
20 | {% endif %} 21 | {% endblock %} 22 | {%- block document %} 23 | {% if documentation_version_warning %} 24 |

Warning: {{ documentation_version_warning }}

25 | {% endif %} 26 | {{ super() }} 27 | {% endblock %} 28 | {%- block footer %} 29 | 33 | {% if pagename == 'index' %} 34 |
35 | {% endif %} 36 | {%- endblock %} 37 | -------------------------------------------------------------------------------- /themes/pocoo/relations.html: -------------------------------------------------------------------------------- 1 |

Related Topics

2 | 20 | -------------------------------------------------------------------------------- /themes/pocoo/searchbox.html: -------------------------------------------------------------------------------- 1 | {%- if pagename != "search" and builder != "singlehtml" %} 2 | 9 | {%- endif %} 10 | -------------------------------------------------------------------------------- /themes/pocoo/sidebarversions.html: -------------------------------------------------------------------------------- 1 |

Versions

2 | 20 | -------------------------------------------------------------------------------- /themes/pocoo/static/pocoo.css_t: -------------------------------------------------------------------------------- 1 | {% set page_width = '940px' %} 2 | {% set sidebar_width = '220px' %} 3 | 4 | @import url("basic.css"); 5 | 6 | /* -- page layout ----------------------------------------------------------- */ 7 | 8 | body { 9 | font-family: sans-serif; 10 | font-size: 17px; 11 | background-color: white; 12 | color: #000; 13 | margin: 0; 14 | padding: 0; 15 | } 16 | 17 | div.document { 18 | width: {{ page_width }}; 19 | margin: 30px auto 0 auto; 20 | } 21 | 22 | div.documentwrapper { 23 | float: left; 24 | width: 100%; 25 | } 26 | 27 | div.bodywrapper { 28 | margin: 0 0 0 {{ sidebar_width }}; 29 | } 30 | 31 | div.sphinxsidebar { 32 | width: {{ sidebar_width }}; 33 | } 34 | 35 | hr { 36 | border: 1px solid #B1B4B6; 37 | } 38 | 39 | div.body { 40 | background-color: #ffffff; 41 | padding: 0 30px 0 30px; 42 | } 43 | 44 | div.footer { 45 | width: {{ page_width }}; 46 | margin: 20px auto 30px auto; 47 | font-size: 14px; 48 | color: #888; 49 | text-align: right; 50 | } 51 | 52 | div.footer a { 53 | color: #888; 54 | } 55 | 56 | div.related { 57 | display: none; 58 | } 59 | 60 | div.sphinxsidebar a { 61 | color: #444; 62 | text-decoration: none; 63 | border-bottom: 1px dotted #999; 64 | } 65 | 66 | div.sphinxsidebar a:hover { 67 | border-bottom: 1px solid #999; 68 | } 69 | 70 | div.sphinxsidebar { 71 | font-size: 14px; 72 | line-height: 1.5; 73 | } 74 | 75 | div.sphinxsidebarwrapper { 76 | padding: 18px 10px; 77 | } 78 | 79 | div.sphinxsidebarwrapper p.logo { 80 | padding: 0 0 20px 0; 81 | margin: 0; 82 | text-align: center; 83 | } 84 | 85 | div.sphinxsidebar h3, 86 | div.sphinxsidebar h4 { 87 | color: #444; 88 | font-size: 24px; 89 | font-weight: normal; 90 | margin: 0 0 5px 0; 91 | padding: 0; 92 | } 93 | 94 | div.sphinxsidebar h4 { 95 | font-size: 20px; 96 | } 97 | 98 | div.sphinxsidebar h3 a { 99 | color: #444; 100 | } 101 | 102 | div.sphinxsidebar p.logo a, 103 | div.sphinxsidebar h3 a, 104 | div.sphinxsidebar p.logo a:hover, 105 | div.sphinxsidebar h3 a:hover { 106 | border: none; 107 | } 108 | 109 | div.sphinxsidebar p { 110 | color: #555; 111 | margin: 10px 0; 112 | } 113 | 114 | div.sphinxsidebar ul { 115 | margin: 10px 0; 116 | padding: 0; 117 | color: #000; 118 | } 119 | 120 | div.sphinxsidebar input { 121 | border: 1px solid #ccc; 122 | font-size: 1em; 123 | } 124 | 125 | div.sphinxsidebar #searchbox input[type="text"] { 126 | width: 142px; 127 | } 128 | 129 | div.sphinxsidebar ul.versions a.current { 130 | font-style: italic; 131 | border-bottom: 1px solid black; 132 | color: black; 133 | } 134 | 135 | div.sphinxsidebar ul.versions span.note { 136 | color: #888; 137 | } 138 | 139 | /* -- warning --------------------------------------------------------------- */ 140 | 141 | p.version-warning { 142 | padding: 0 10px; 143 | height: 28px!important; 144 | line-height: 28px!important; 145 | font-size: 17px; 146 | margin: 0 0 10px 0; 147 | border-radius: 2px; 148 | 149 | letter-spacing: 1px; 150 | font-size: 13px; 151 | color: white; 152 | text-align: center; 153 | 154 | background: #d40; 155 | background-size: 28px 28px; 156 | background-image: linear-gradient(-45deg, 157 | rgba(255, 255, 255, 0.2) 0%, 158 | rgba(255, 255, 255, 0.2) 25%, 159 | transparent 25%, 160 | transparent 50%, 161 | rgba(255, 255, 255, 0.2) 50%, 162 | rgba(255, 255, 255, 0.2) 75%, 163 | transparent 75%, 164 | transparent 165 | ); 166 | } 167 | 168 | /* -- body styles ----------------------------------------------------------- */ 169 | 170 | a { text-decoration: underline; } 171 | 172 | div.body h1, 173 | div.body h2, 174 | div.body h3, 175 | div.body h4, 176 | div.body h5, 177 | div.body h6 { 178 | font-weight: normal; 179 | margin: 30px 0px 10px 0px; 180 | padding: 0; 181 | } 182 | 183 | div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } 184 | div.body h2 { font-size: 180%; } 185 | div.body h3 { font-size: 150%; } 186 | div.body h4 { font-size: 130%; } 187 | div.body h5 { font-size: 100%; } 188 | div.body h6 { font-size: 100%; } 189 | 190 | a.headerlink { 191 | color: #ddd; 192 | padding: 0 4px; 193 | text-decoration: none; 194 | } 195 | 196 | a.headerlink:hover { 197 | color: #444; 198 | background: #eaeaea; 199 | } 200 | 201 | div.body p, div.body dd, div.body li { 202 | line-height: 1.4em; 203 | } 204 | 205 | div.admonition { 206 | background: #fafafa; 207 | margin: 20px -30px; 208 | padding: 10px 30px; 209 | border-top: 1px solid #ccc; 210 | border-bottom: 1px solid #ccc; 211 | } 212 | 213 | div.admonition code.xref, div.admonition a code { 214 | border-bottom: 1px solid #fafafa; 215 | } 216 | 217 | dd div.admonition { 218 | margin-left: -60px; 219 | padding-left: 60px; 220 | } 221 | 222 | div.admonition p.admonition-title { 223 | font-weight: normal; 224 | font-size: 24px; 225 | margin: 0 0 10px 0; 226 | padding: 0; 227 | line-height: 1; 228 | } 229 | 230 | div.admonition p.last { 231 | margin-bottom: 0; 232 | } 233 | 234 | div.highlight { 235 | background-color: white; 236 | } 237 | 238 | dt:target, .highlight { 239 | background: #FAF3E8; 240 | } 241 | 242 | div.note { 243 | background-color: #eee; 244 | border: 1px solid #ccc; 245 | } 246 | 247 | div.seealso { 248 | background-color: #ffc; 249 | border: 1px solid #ff6; 250 | } 251 | 252 | div.topic { 253 | background-color: #eee; 254 | } 255 | 256 | p.admonition-title { 257 | display: inline; 258 | } 259 | 260 | p.admonition-title:after { 261 | content: ":"; 262 | } 263 | 264 | pre, code { 265 | font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; 266 | font-size: 0.9em; 267 | } 268 | 269 | img.screenshot { 270 | } 271 | 272 | code.descname, code.descclassname { 273 | font-size: 0.95em; 274 | } 275 | 276 | code.descname { 277 | padding-right: 0.08em; 278 | } 279 | 280 | img.screenshot { 281 | -moz-box-shadow: 2px 2px 4px #eee; 282 | -webkit-box-shadow: 2px 2px 4px #eee; 283 | box-shadow: 2px 2px 4px #eee; 284 | } 285 | 286 | table.docutils { 287 | border: 1px solid #888; 288 | -moz-box-shadow: 2px 2px 4px #eee; 289 | -webkit-box-shadow: 2px 2px 4px #eee; 290 | box-shadow: 2px 2px 4px #eee; 291 | } 292 | 293 | table.docutils td, table.docutils th { 294 | border: 1px solid #888; 295 | padding: 0.25em 0.7em; 296 | } 297 | 298 | table.field-list, table.footnote { 299 | border: none; 300 | -moz-box-shadow: none; 301 | -webkit-box-shadow: none; 302 | box-shadow: none; 303 | } 304 | 305 | table.footnote { 306 | margin: 15px 0; 307 | width: 100%; 308 | border: 1px solid #eee; 309 | background: #fdfdfd; 310 | font-size: 0.9em; 311 | } 312 | 313 | table.footnote + table.footnote { 314 | margin-top: -15px; 315 | border-top: none; 316 | } 317 | 318 | table.field-list th { 319 | padding: 0 0.8em 0 0; 320 | } 321 | 322 | table.field-list td { 323 | padding: 0; 324 | } 325 | 326 | table.footnote td.label { 327 | width: 0px; 328 | padding: 0.3em 0 0.3em 0.5em; 329 | } 330 | 331 | table.footnote td { 332 | padding: 0.3em 0.5em; 333 | } 334 | 335 | dl { 336 | margin: 0; 337 | padding: 0; 338 | } 339 | 340 | dl dd { 341 | margin-left: 30px; 342 | } 343 | 344 | blockquote { 345 | margin: 0 0 0 30px; 346 | padding: 0; 347 | } 348 | 349 | ul, ol { 350 | margin: 10px 0 10px 30px; 351 | padding: 0; 352 | } 353 | 354 | pre { 355 | background: #eee; 356 | padding: 7px 30px; 357 | margin: 15px -30px; 358 | line-height: 1.3em; 359 | } 360 | 361 | dl pre, blockquote pre, li pre { 362 | margin-left: -60px; 363 | padding-left: 60px; 364 | } 365 | 366 | dl dl pre { 367 | margin-left: -90px; 368 | padding-left: 90px; 369 | } 370 | 371 | code { 372 | background-color: #ecf0f3; 373 | color: #222; 374 | /* padding: 1px 2px; */ 375 | } 376 | 377 | code.xref, a code { 378 | background-color: #FBFBFB; 379 | border-bottom: 1px solid white; 380 | } 381 | 382 | a.reference { 383 | text-decoration: none; 384 | } 385 | 386 | a.footnote-reference { 387 | text-decoration: none; 388 | font-size: 0.7em; 389 | vertical-align: top; 390 | } 391 | 392 | a:hover code { 393 | background: #EEE; 394 | } 395 | 396 | /* carbon ads */ 397 | div.carbon_ads { 398 | text-align: center; 399 | overflow: hidden; 400 | margin: 15px 0; 401 | border: 1px solid #ccc; 402 | background: #eee; 403 | padding: 10px 7px; 404 | } 405 | 406 | div.carbon_ads a.carbon-img { 407 | display: block; 408 | margin-bottom: 7px; 409 | border: none; 410 | } 411 | 412 | div.carbon_ads a.carbon-poweredby { 413 | margin-top: 7px; 414 | margin-left: 15px; 415 | float: right; 416 | font-size: 11px; 417 | } 418 | -------------------------------------------------------------------------------- /themes/pocoo/static/small.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 20px 30px; 4 | } 5 | 6 | div.documentwrapper { 7 | float: none; 8 | background: white; 9 | } 10 | 11 | div.sphinxsidebar { 12 | display: block; 13 | float: none; 14 | width: 102.5%; 15 | margin: 50px -30px -20px -30px; 16 | padding: 10px 20px; 17 | background: #333; 18 | color: white; 19 | } 20 | 21 | div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, 22 | div.sphinxsidebar h3 a { 23 | color: white; 24 | } 25 | 26 | div.sphinxsidebar a { 27 | color: #aaa; 28 | } 29 | 30 | div.sphinxsidebar p.logo { 31 | display: none; 32 | } 33 | 34 | div.sphinxsidebar ul.versions a.current { 35 | font-style: italic; 36 | border-bottom: 1px solid white; 37 | color: white; 38 | } 39 | 40 | div.document { 41 | width: 100%; 42 | margin: 0; 43 | } 44 | 45 | div.related { 46 | display: block; 47 | margin: 0; 48 | padding: 10px 0 20px 0; 49 | } 50 | 51 | div.related ul, 52 | div.related ul li { 53 | margin: 0; 54 | padding: 0; 55 | } 56 | 57 | div.footer { 58 | display: none; 59 | } 60 | 61 | div.bodywrapper { 62 | margin: 0; 63 | } 64 | 65 | div.body { 66 | min-height: 0; 67 | padding: 0; 68 | } 69 | -------------------------------------------------------------------------------- /themes/pocoo/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = pocoo.css 4 | pygments_style = pocoo_theme_support.FlaskyStyle 5 | -------------------------------------------------------------------------------- /themes/pocoo_theme_support.py: -------------------------------------------------------------------------------- 1 | from pygments.style import Style 2 | from pygments.token import Keyword, Name, Comment, String, Error, \ 3 | Number, Operator, Generic, Whitespace, Punctuation, Other, Literal 4 | 5 | 6 | class PocooStyle(Style): 7 | background_color = "#f8f8f8" 8 | default_style = "" 9 | 10 | styles = { 11 | # No corresponding class for the following: 12 | #Text: "", # class: '' 13 | Whitespace: "underline #f8f8f8", # class: 'w' 14 | Error: "#a40000 border:#ef2929", # class: 'err' 15 | Other: "#000000", # class 'x' 16 | 17 | Comment: "italic #8f5902", # class: 'c' 18 | Comment.Preproc: "noitalic", # class: 'cp' 19 | 20 | Keyword: "bold #004461", # class: 'k' 21 | Keyword.Constant: "bold #004461", # class: 'kc' 22 | Keyword.Declaration: "bold #004461", # class: 'kd' 23 | Keyword.Namespace: "bold #004461", # class: 'kn' 24 | Keyword.Pseudo: "bold #004461", # class: 'kp' 25 | Keyword.Reserved: "bold #004461", # class: 'kr' 26 | Keyword.Type: "bold #004461", # class: 'kt' 27 | 28 | Operator: "#582800", # class: 'o' 29 | Operator.Word: "bold #004461", # class: 'ow' - like keywords 30 | 31 | Punctuation: "bold #000000", # class: 'p' 32 | 33 | # because special names such as Name.Class, Name.Function, etc. 34 | # are not recognized as such later in the parsing, we choose them 35 | # to look the same as ordinary variables. 36 | Name: "#000000", # class: 'n' 37 | Name.Attribute: "#c4a000", # class: 'na' - to be revised 38 | Name.Builtin: "#004461", # class: 'nb' 39 | Name.Builtin.Pseudo: "#3465a4", # class: 'bp' 40 | Name.Class: "#000000", # class: 'nc' - to be revised 41 | Name.Constant: "#000000", # class: 'no' - to be revised 42 | Name.Decorator: "#888", # class: 'nd' - to be revised 43 | Name.Entity: "#ce5c00", # class: 'ni' 44 | Name.Exception: "bold #cc0000", # class: 'ne' 45 | Name.Function: "#000000", # class: 'nf' 46 | Name.Property: "#000000", # class: 'py' 47 | Name.Label: "#f57900", # class: 'nl' 48 | Name.Namespace: "#000000", # class: 'nn' - to be revised 49 | Name.Other: "#000000", # class: 'nx' 50 | Name.Tag: "bold #004461", # class: 'nt' - like a keyword 51 | Name.Variable: "#000000", # class: 'nv' - to be revised 52 | Name.Variable.Class: "#000000", # class: 'vc' - to be revised 53 | Name.Variable.Global: "#000000", # class: 'vg' - to be revised 54 | Name.Variable.Instance: "#000000", # class: 'vi' - to be revised 55 | 56 | Number: "#990000", # class: 'm' 57 | 58 | Literal: "#000000", # class: 'l' 59 | Literal.Date: "#000000", # class: 'ld' 60 | 61 | String: "#4e9a06", # class: 's' 62 | String.Backtick: "#4e9a06", # class: 'sb' 63 | String.Char: "#4e9a06", # class: 'sc' 64 | String.Doc: "italic #8f5902", # class: 'sd' - like a comment 65 | String.Double: "#4e9a06", # class: 's2' 66 | String.Escape: "#4e9a06", # class: 'se' 67 | String.Heredoc: "#4e9a06", # class: 'sh' 68 | String.Interpol: "#4e9a06", # class: 'si' 69 | String.Other: "#4e9a06", # class: 'sx' 70 | String.Regex: "#4e9a06", # class: 'sr' 71 | String.Single: "#4e9a06", # class: 's1' 72 | String.Symbol: "#4e9a06", # class: 'ss' 73 | 74 | Generic: "#000000", # class: 'g' 75 | Generic.Deleted: "#a40000", # class: 'gd' 76 | Generic.Emph: "italic #000000", # class: 'ge' 77 | Generic.Error: "#ef2929", # class: 'gr' 78 | Generic.Heading: "bold #000080", # class: 'gh' 79 | Generic.Inserted: "#00A000", # class: 'gi' 80 | Generic.Output: "#888", # class: 'go' 81 | Generic.Prompt: "#745334", # class: 'gp' 82 | Generic.Strong: "bold #000000", # class: 'gs' 83 | Generic.Subheading: "bold #800080", # class: 'gu' 84 | Generic.Traceback: "bold #a40000", # class: 'gt' 85 | } 86 | -------------------------------------------------------------------------------- /themes/werkzeug/search.html: -------------------------------------------------------------------------------- 1 | {%- extends "layout.html" %} 2 | {% from "customsearch.html" import render_gcs, render_gcs_style %} 3 | {% set title = _('Search') %} 4 | {% block body %} 5 |

Search

6 | {{ render_gcs('012722186170730423054:2lbcxavx8gk') }} 7 | {{ render_gcs_style( 8 | font_family="'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif", 9 | font_size='15px', 10 | primary_color='#185F6D', 11 | link_hover_color='#2794AA', 12 | secondary_color='#2794AA', 13 | highlight_color='#E8EFF0' 14 | ) }} 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /themes/werkzeug/sidebarintro.html: -------------------------------------------------------------------------------- 1 |

About Werkzeug

2 |

3 | Werkzeug is an HTTP and WSGI utility library for Python. 4 |

5 |

Useful Links

6 | 12 | -------------------------------------------------------------------------------- /themes/werkzeug/sidebarlogo.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /themes/werkzeug/static/werkzeug.css: -------------------------------------------------------------------------------- 1 | @import url(pocoo.css); 2 | @import url(http://fonts.googleapis.com/css?family=Ubuntu); 3 | 4 | /* fonts */ 5 | body { font-family: 'Lucida Grande', 'Lucida Sans Unicode', 6 | 'Geneva', 'Verdana', sans-serif; font-size: 15px; } 7 | div.admonition p.admonition-title, div.sphinxsidebar h3, div.sphinxsidebar h4, 8 | div.sphinxsidebar input, div.body h1, div.body h2, div.body h3, div.body h4, 9 | div.body h5, div.body h6 { font-family: 'Ubuntu', 'Lucida Grande', sans-serif; } 10 | div.body h1, div.body h2, div.body h3, div.body h4, 11 | div.body h5, div.body h6 { color: black; } 12 | pre, code { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 13 | 'Bitstream Vera Sans Mono', monospace; 14 | font-size: 0.9em; } 15 | 16 | /* colors */ 17 | div.body { color: #3E4349; } 18 | a { color: #185F6D; } 19 | a:hover { color: #2794AA; } 20 | p.version-warning { background-color: #FF8C08; } 21 | a.reference { border-bottom: 1px dotted #2BABC4; } 22 | a.footnote-reference { border-bottom: 1px dotted #004B6B; } 23 | a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } 24 | code { background-color: #E8EFF0; color: #222; } 25 | code.xref, a code { background-color: #E8EFF0; 26 | border-bottom: 1px solid white; } 27 | -------------------------------------------------------------------------------- /themes/werkzeug/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = pocoo 3 | stylesheet = werkzeug.css 4 | --------------------------------------------------------------------------------