Skip to content

Commit

Permalink
[ADD] doc: new theme
Browse files Browse the repository at this point in the history
Pretty much completely rewritten theme with custom HTML translator and a
few parts of the old theme extracted to their own extensions.

Banner images thought not to be that huge after all, and not worth the
hassle of them living in a different repository.

co-authored with @stefanorigano
  • Loading branch information
xmo-odoo committed Jul 7, 2015
1 parent b4efb4e commit 95e56a1
Show file tree
Hide file tree
Showing 256 changed files with 15,858 additions and 12,388 deletions.
5 changes: 5 additions & 0 deletions doc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,8 @@ doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
# -*- coding: utf-8 -*-
from . import html_domain
from . import github
# add Odoo style to pygments
from . import odoo_pygments

from . import sphinx_monkeypatch
sphinx_monkeypatch.patch()
"""
Adds a new "exercise" admonition type
"""

def setup(app):
html_domain.setup(app)
github.setup(app)

app.add_directive('exercise', Exercise)
app.add_node(exercise, html=(
lambda self, node: self.visit_admonition(node, 'exercise'),
Expand All @@ -28,8 +22,3 @@ class Exercise(admonitions.BaseAdmonition):

from sphinx.locale import admonitionlabels, l_
admonitionlabels['exercise'] = l_('Exercise')

# monkeypatch PHP lexer to not require <?php
from sphinx.highlighting import lexers
from pygments.lexers.web import PhpLexer
lexers['php'] = PhpLexer(startinline=True)
31 changes: 29 additions & 2 deletions doc/_themes/odoodoc/github.py → doc/_extensions/github_link.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@
import os.path
from urlparse import urlunsplit

"""
* adds github_link(mode) context variable: provides URL (in relevant mode) of
current document on github
* if sphinx.ext.linkcode is enabled, automatically generates github linkcode
links (by setting config.linkcode_resolve)
Settings
========
* ``github_user``, username/organisation under which the project lives
* ``github_project``, name of the project on github
* (optional) ``version``, github branch to link to (default: master)
Notes
=====
* provided ``linkcode_resolve`` only supports Python domain
* generates https github links
* explicitly imports ``openerp``, so useless for anyone else
"""

def setup(app):
app.add_config_value('github_user', None, 'env')
app.add_config_value('github_project', None, 'env')
Expand Down Expand Up @@ -42,6 +63,7 @@ def linkcode_resolve(domain, info):
return None

import openerp
# FIXME: make finding project root project-independent
project_root = os.path.join(os.path.dirname(openerp.__file__), '..')
return make_github_link(
app,
Expand Down Expand Up @@ -72,6 +94,11 @@ def add_doc_link(app, pagename, templatename, context, doctree):
if not app.config.github_user and app.config.github_project:
return

# FIXME: find other way to recover current document's source suffix
# in Sphinx 1.3 it's possible to have mutliple source suffixes and that
# may be useful in the future
source_suffix = app.config.source_suffix
source_suffix = source_suffix if isinstance(source_suffix, basestring) else source_suffix[0]
# can't use functools.partial because 3rd positional is line not mode
context['github_link'] = lambda mode='mode': make_github_link(
app, 'doc/%s%s' % (pagename, app.config.source_suffix), mode=mode)
context['github_link'] = lambda mode='edit': make_github_link(
app, 'doc/%s%s' % (pagename, source_suffix), mode=mode)
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
# -*- coding: utf-8 -*-

"""
Defines a "raw HTML" domain with a ``div[classes]`` and a number of roles
rendered more or less directly to HTML.
.. warning::
the purpose of this domain is *not* to document HTML or components
"""

from docutils import nodes, utils
from docutils.parsers.rst import Directive, directives, docutils
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives.body import LineBlock

import sphinx.roles
Expand Down
100 changes: 100 additions & 0 deletions doc/_extensions/odoo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-

from . import switcher
from . import pygments_override
import collections

import sphinx.environment
import sphinx.builders.html
from docutils import nodes
def setup(app):
switcher.setup(app)
app.add_config_value('odoo_cover_default', None, 'env')
app.add_config_value('odoo_cover_external', {}, 'env')
app.add_config_value('odoo_cover_default_external', lambda conf: conf.odoo_cover_default, 'env')
app.connect('html-page-context', update_meta)

def update_meta(app, pagename, templatename, context, doctree):
meta = context.setdefault('meta', {})
meta.setdefault('banner', app.config.odoo_cover_default)

def navbarify(node, navbar=None):
"""
:param node: toctree node to navbarify
:param navbar: Whether this toctree is a 'main' navbar, a 'side' navbar or
not a navbar at all
"""
if navbar == 'main':
# add classes to just toplevel
node['classes'].extend(['nav', 'navbar-nav', 'navbar-right'])
for list_item in node.children:
# bullet_list
# list_item
# compact_paragraph
# reference
# bullet_list
# list_item
# compact_paragraph
# reference
# no bullet_list.list_item -> don't dropdownify
if len(list_item.children) < 2 or not list_item.children[1].children:
continue

list_item['classes'].append('dropdown')
# list_item.compact_paragraph.reference
link = list_item.children[0].children[0]
link['classes'].append('dropdown-toggle')
link.attributes['data-toggle'] = 'dropdown'
# list_item.bullet_list
list_item.children[1]['classes'].append('dropdown-menu')

def resolve_content_toctree(
environment, docname, builder, toctree, prune=True, maxdepth=0,
titles_only=False, collapse=False, includehidden=False):
"""Alternative toctree resolution for main content: don't resolve the
toctree, just handle it as a normal node, in the translator
"""
return toctree

class monkey(object):
def __init__(self, obj):
self.obj = obj
def __call__(self, fn):
name = fn.__name__
old = getattr(self.obj, name)
setattr(self.obj, name, lambda self_, *args, **kwargs: \
fn(old, self_, *args, **kwargs))

@monkey(sphinx.environment.BuildEnvironment)
def resolve_toctree(old_resolve, self, docname, *args, **kwargs):
""" If navbar, bootstrapify TOC to yield a navbar
"""
navbar = kwargs.pop('navbar', None)
if docname == self.config.master_doc and not navbar:
return resolve_content_toctree(self, docname, *args, **kwargs)
toc = old_resolve(self, docname, *args, **kwargs)
if toc is None:
return None

navbarify(toc[0], navbar=navbar)
return toc

@monkey(sphinx.builders.html.StandaloneHTMLBuilder)
def render_partial(old_partial, self, node):
if isinstance(node, nodes.bullet_list) and node.children:
# side nav?
# remove single top-level item
# bullet_list/0(list_item)/1(bullet_list)
level1 = node.children[0].children
if len(level1) > 1:
node = level1[1]
node['classes'].extend(['list-group', 'nav', 'text-left'])
for n in node.traverse():
if isinstance(n, nodes.list_item):
n['classes'].append('list-group-item')
elif isinstance(n, nodes.reference):
n['classes'].append('ripple')
else:
node.clear()
return old_partial(self, node)
135 changes: 135 additions & 0 deletions doc/_extensions/odoo/layout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
{% extends "basic/layout.html" %}

{% set script_files = script_files + [
'_static/jquery.min.js',
'_static/bootstrap.js',
'_static/doc.js',
'_static/jquery.noconflict.js',
] %}

{% set classes = [] %}
{% if pagename == master_doc %}
{% set classes = classes + ['index'] %}
{% endif %}
{% if 'code-column' in meta %}
{% set classes = classes + ['has_code_col'] %}
{% endif %}

{%- block doctype -%}
<!doctype html>
{%- endblock -%}
{%- block htmltitle -%}
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{{ super() }}
{%- endblock -%}

{%- block sidebar1 -%}{%- endblock -%}
{%- block sidebar2 -%}{%- endblock -%}
{%- block relbar1 -%}{%- endblock -%}
{%- block relbar2 -%}{%- endblock -%}

{%- block footer -%}
{%- if google_analytics_key -%}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', '{{ google_analytics_key }}', 'auto');
ga('send','pageview');
</script>
{%- endif -%}
{%- endblock -%}

{%- block header -%}
<header class="{{ ' '.join(classes) }}">
<figure class="card top">
<span class="card-img" style="background-image: url('{{ pathto('_static/' + meta['banner'], True) }}');"></span>
</figure>
</header>
<nav id="main_navbar" class="navbar {{ ' '.join(classes) }}">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".navbar-main">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<nav class="nav navbar-nav navbar-left">
<li id="main-back"><a href="{{ pathto(master_doc) }}" class="mdi-navigation-arrow-back"></a></li>
<li>
<h1 id="main_title">{{ meta.get('main-title', title) }}</h1>
</li>
</nav>
</div>

<nav class="collapse navbar-collapse navbar-main navbar-right" role="navigation">
{% if versions %}
<ul class="navbar-nav navbar-right nav">
<li class="versions">
<a class="dropdown-toggle" data-toggle="dropdown">
{{ version }} <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
{% for name, url in versions %}
<li><a href="{{ url }}">{{ name }}</a></li>
{% endfor %}
</ul>
</li>
</ul>
{% endif %}
{{ toctree(titles_only=True, maxdepth=2, includehidden=True,
collapse=False, navbar='main') }}
</nav>
</div>
</nav>
{%- endblock -%}

{%- block content -%}
<main class="container {{ ' '.join(classes) }}">
{% if pagename != master_doc %}
<div class="row">
<aside>
<div class="navbar-aside text-center">
<div class="logo_box">
<span class="logo"></span>
Documentation
</div>
<h3 class="muted">Contents</h3>
{{ toc }}
{% if github_link %}
<p class="gith-container"><a href="{{ github_link(mode='edit') }}" class="gith-link">
Edit on GitHub
</a></p>
{% endif %}
</div>
</aside>
<article class="doc-body">
{% endif %}
{% block body %} {% endblock %}
{% if pagename != master_doc %}</article>
</div>
{% endif %}
<div id="mask"></div>
</main>

<div class="floating_action_container">
<a id="floating_action" class="ripple" href="#">
<i class="mdi-action-explore"></i>
</a>
<div id="floating_action_menu">
<span class="bubble"></span>
<ul class="list-group content">
<li class="list-group-item ripple"><a>Cras justo odio</a></li>
<li class="list-group-item ripple"><a>Dapibus ac facilisis in</a></li>
<li class="list-group-item ripple"><a>Morbi leo risus</a></li>
<li class="list-group-item ripple"><a>Porta ac consectetur ac</a></li>
<li class="list-group-item ripple"><a>Vestibulum at eros</a></li>
</ul>
</div>
</div>
{%- endblock -%}
20 changes: 20 additions & 0 deletions doc/_extensions/odoo/pygments_override.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from pygments.style import Style
from pygments.styles.paraiso_dark import ParaisoDarkStyle
from pygments.token import *

# extracted from getbootstrap.com
class OdooStyle(Style):
background_color = '#272727'
highlight_color = ParaisoDarkStyle.highlight_color

styles = dict(ParaisoDarkStyle.styles)
styles[Keyword] = '#cb49a8'
styles[Name.Tag] = '#21b799'

import imp
import sys
modname = 'pygments.styles.odoo'
m = imp.new_module(modname)
m.OdooStyle = OdooStyle
sys.modules[modname] = m
Loading

0 comments on commit 95e56a1

Please sign in to comment.