diff --git a/_extensions/github_link.py b/_extensions/github_link.py index 537280c00..8f7a00840 100644 --- a/_extensions/github_link.py +++ b/_extensions/github_link.py @@ -1,8 +1,8 @@ import inspect import importlib import os.path -import werkzeug +from werkzeug import urls """ * adds github_link(mode) context variable: provides URL (in relevant mode) of @@ -22,7 +22,7 @@ Notes * provided ``linkcode_resolve`` only supports Python domain * generates https github links -* explicitly imports ``openerp``, so useless for anyone else +* explicitly imports ``odoo``, so useless for anyone else """ def setup(app): @@ -63,9 +63,9 @@ def setup(app): # obj doesn't have a module, or something return None - import openerp + import odoo # FIXME: make finding project root project-independent - project_root = os.path.join(os.path.dirname(openerp.__file__), '..') + project_root = os.path.join(os.path.dirname(odoo.__file__), '..') return make_github_link( app, os.path.relpath(obj_source_path, project_root), @@ -82,25 +82,24 @@ def make_github_link(app, path, line=None, mode="blob"): path=path, mode=mode, ) - return werkzeug.urls.url_unparse(( + return urls.url_unparse(( 'https', 'github.com', urlpath, '', '' if line is None else 'L%d' % line )) - def add_doc_link(app, pagename, templatename, context, doctree): """ Add github_link function linking to the current page on github """ 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 = next(iter(source_suffix)) - # FIXME: odoo/odoo has a doc/ prefix which is incorrect for this - # project, how to unify? Add new setting? + # in 1.3 source_suffix can be a list + # in 1.8 source_suffix can be a mapping + # FIXME: will break if we ever add support for !rst markdown documents maybe + if not isinstance(source_suffix, str): + source_suffix = next(iter(source_suffix)) + # can't use functools.partial because 3rd positional is line not mode context['github_link'] = lambda mode='edit': make_github_link( - app, '%s%s' % (pagename, source_suffix), mode=mode) + app, 'doc/%s%s' % (pagename, source_suffix), mode=mode) diff --git a/_extensions/odoo/__init__.py b/_extensions/odoo/__init__.py index e3473c996..e4191e900 100644 --- a/_extensions/odoo/__init__.py +++ b/_extensions/odoo/__init__.py @@ -21,6 +21,10 @@ def setup(app): location="odoo extension") app.config.html_translator_class = 'odoo.translator.BootstrapTranslator' + add_js_file = getattr(app, 'add_js_file', None) or app.add_javascript + for f in ['jquery.min.js', 'bootstrap.js', 'doc.js', 'jquery.noconflict.js']: + add_js_file(f) + switcher.setup(app) app.add_config_value('odoo_cover_default', None, 'env') app.add_config_value('odoo_cover_external', {}, 'env') @@ -28,9 +32,9 @@ def setup(app): app.connect('html-page-context', update_meta) def update_meta(app, pagename, templatename, context, doctree): - if not context.get('meta'): # context['meta'] can be None - context['meta'] = {} - meta = context.setdefault('meta', {}) # we want {} by default + meta = context.get('meta') + if meta is None: + meta = context['meta'] = {} meta.setdefault('banner', app.config.odoo_cover_default) def navbarify(node, navbar=None): @@ -107,13 +111,7 @@ if toctree: def resolve(old_resolve, tree, docname, *args, **kwargs): if docname == tree.env.config.master_doc: return resolve_content_toctree(tree.env, docname, *args, **kwargs) - toc = old_resolve(tree, docname, *args, **kwargs) - if toc is None: - return None - - navbarify(toc[0], navbar=kwargs.pop('navbar', None)) - return toc - + return old_resolve(tree, docname, *args, **kwargs) @monkey(sphinx.environment.BuildEnvironment) def resolve_toctree(old_resolve, self, docname, *args, **kwargs): diff --git a/_extensions/odoo/breadcrumb_list.html b/_extensions/odoo/breadcrumb_list.html index 2c83929dc..9d670a487 100644 --- a/_extensions/odoo/breadcrumb_list.html +++ b/_extensions/odoo/breadcrumb_list.html @@ -1,7 +1,7 @@ {# warning: if doc structure change, these rules may have to change as well #} {# ===== VARIABLES ====== #} -{% set master_doc_short_name = 'User Doc' %} +{% set master_doc_short_name = 'Developer Doc' %} {% if pagename == master_doc %}
  • {{ master_doc_short_name }}
  • diff --git a/_extensions/odoo/layout.html b/_extensions/odoo/layout.html index 4dd56e5a9..368ccfc45 100644 --- a/_extensions/odoo/layout.html +++ b/_extensions/odoo/layout.html @@ -1,13 +1,4 @@ {% extends "basic/layout.html" %} -{% set html5_doctype = True %} - -{%- block scripts %} - {{ super() }} - - - - -{%- endblock %} {% set classes = [] %} {% if pagename == master_doc %} @@ -18,18 +9,16 @@ {% set classes = classes + ['has_code_col'] %} {% endif %} -{% if 'classes' in meta %} - {% set classes = classes + meta['classes'].split() %} -{% endif %} - -{%- block linktags -%} - {% for code, url in language_codes %} - - {%- endfor %} - - {{ super() }} +{%- block doctype -%} + {%- endblock -%} +{%- block linktags %} + + + {{- super() }} +{%- endblock %} + {%- block sidebar1 -%}{%- endblock -%} {%- block sidebar2 -%}{%- endblock -%} {%- block relbar1 -%}{%- endblock -%} @@ -44,7 +33,6 @@ })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', '{{ google_analytics_key }}', 'auto'); - ga('set', 'anonymizeIp', true); ga('send','pageview'); {%- endif -%} @@ -77,8 +65,8 @@
  • eCommerce
  • Blogs
  • Forums
  • -
  • eLearning
  • -
  • Live Chat
  • +
  • Slides
  • +
  • SEA
  • @@ -95,12 +83,10 @@
  • Subscriptions
  • Sign
  • -
  • Rental
  • @@ -109,17 +95,17 @@
    It's all about efficiency
    -
  • Helpdesk
  • -
  • Field Service
  • @@ -149,23 +133,15 @@
  • Discuss
  • Mailing Lists
  • Notes
  • +
  • Help desk
  • +
  • Appointment
  • Timesheet
  • +
  • Email Marketing
  • Events
  • -
  • Survey
  • -
  • Approvals
  • -
  • Appointments
  • -
  • Documents
  • +
  • Live Chat
  • @@ -198,6 +174,16 @@ Start Now + + - - @@ -361,4 +337,3 @@ {%- endblock -%} - diff --git a/_extensions/odoo/pygments_override.py b/_extensions/odoo/pygments_override.py index d03fb4f0e..aa03003c0 100644 --- a/_extensions/odoo/pygments_override.py +++ b/_extensions/odoo/pygments_override.py @@ -118,9 +118,9 @@ class OdooStyle(Style): Generic.Traceback: "", } -import imp +import types import sys modname = 'pygments.styles.odoo' -m = imp.new_module(modname) +m = types.ModuleType(modname) m.OdooStyle = OdooStyle sys.modules[modname] = m diff --git a/_extensions/odoo/static/components.less b/_extensions/odoo/static/components.less index 678ac4bce..c170369bc 100644 --- a/_extensions/odoo/static/components.less +++ b/_extensions/odoo/static/components.less @@ -124,7 +124,6 @@ article.doc-body .code-fields { margin: 0; padding: 0 0 2%; .transform-origin(50% 0px 0px); - .o-gradient(); @media screen and (min-width: @screen-sm-min) { padding: 12% 0 5%; diff --git a/_extensions/odoo/static/doc.js b/_extensions/odoo/static/doc.js index 768dcc8f2..af0a1fe0f 100644 --- a/_extensions/odoo/static/doc.js +++ b/_extensions/odoo/static/doc.js @@ -403,4 +403,3 @@ } }); })(jQuery); - diff --git a/_extensions/odoo/static/index.less b/_extensions/odoo/static/index.less index a5642c082..d08a38f97 100644 --- a/_extensions/odoo/static/index.less +++ b/_extensions/odoo/static/index.less @@ -109,12 +109,6 @@ main.index { display: none; } } - a { - text-decoration: none; - &:hover { - text-decoration: underline; - } - } } } } diff --git a/_extensions/odoo/static/style.css b/_extensions/odoo/static/style.css index 751cdde03..436871ca7 100644 --- a/_extensions/odoo/static/style.css +++ b/_extensions/odoo/static/style.css @@ -9384,6 +9384,16 @@ h6 { color: white; } } +.footnote-ref { + vertical-align: super; + font-size: 1ex; +} +.footnote-ref:before { + content: '['; +} +.footnote-ref:after { + content: ']'; +} article.doc-body > section { padding-bottom: 10px; } @@ -9665,12 +9675,6 @@ article.doc-body .code-fields ul em { -moz-transform-origin: 50% 0px 0px; -ms-transform-origin: 50% 0px 0px; transform-origin: 50% 0px 0px; - background: #75526b; - background: -webkit-linear-gradient(99deg, #875A7B 10%, #62495B 90%); - background: -moz-linear-gradient(99deg, #875A7B 10%, #62495B 90%); - background: -ms-linear-gradient(99deg, #875A7B 10%, #62495B 90%); - background: -o-linear-gradient(99deg, #875A7B 10%, #62495B 90%); - background: linear-gradient(99deg, #875A7B 10%, #62495B 90%); } @media screen and (min-width: 768px) { .card.top { @@ -10310,12 +10314,6 @@ main.index .card figcaption { .toctree-wrapper > ul li.toctree-l2 > ul:empty { display: none; } -.toctree-wrapper > ul li.toctree-l2 a { - text-decoration: none; -} -.toctree-wrapper > ul li.toctree-l2 a:hover { - text-decoration: underline; -} #oe_main_menu_navbar ~ #wrapwrap .o_main_header.o_has_sub_nav.o_scrolled { top: -17px; } diff --git a/_extensions/odoo/static/style.less b/_extensions/odoo/static/style.less index 4ea0bfc49..769fcaa8c 100644 --- a/_extensions/odoo/static/style.less +++ b/_extensions/odoo/static/style.less @@ -29,7 +29,7 @@ background-color: @footer-bg-color; color: @gray-lighter; } - + > .o_sub_nav #o_sub-menu #searchbox { display: flex; align-items: center; diff --git a/_extensions/odoo/static/typography.less b/_extensions/odoo/static/typography.less index 0f4528334..c22541843 100644 --- a/_extensions/odoo/static/typography.less +++ b/_extensions/odoo/static/typography.less @@ -33,6 +33,13 @@ h1, h2, h3, h4, h5, h6 { border-bottom: 2px solid #f4f6f7; } +.footnote-ref { + &:before {content: '[';} + &:after {content: ']';} + vertical-align: super; + font-size: 1ex; +} + article.doc-body { // Vertical rhythm diff --git a/_extensions/odoo/sub-menu_list.html b/_extensions/odoo/sub-menu_list.html index 1db5ba604..56d35c609 100644 --- a/_extensions/odoo/sub-menu_list.html +++ b/_extensions/odoo/sub-menu_list.html @@ -2,9 +2,8 @@
  • User
  • Developer
  • -
  • eLearning
  • -
  • API
  • Installation
  • +
  • eLearning
  • White Papers
  • Legal
  • diff --git a/_extensions/odoo/switcher.py b/_extensions/odoo/switcher.py index 51fb60492..8571d1242 100644 --- a/_extensions/odoo/switcher.py +++ b/_extensions/odoo/switcher.py @@ -1,7 +1,8 @@ from docutils import nodes, utils from docutils.parsers.rst import Directive -from pygments.lexers import get_lexer_by_name +from pygments.lexers import get_lexer_by_name, PythonLexer +PythonLexer.name = 'Python 2' def setup(app): app.add_directive('switcher', SwitcherDirective) diff --git a/_extensions/odoo/translator.py b/_extensions/odoo/translator.py index b2579ec4c..982e6040c 100644 --- a/_extensions/odoo/translator.py +++ b/_extensions/odoo/translator.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +from __future__ import print_function + import os.path import posixpath import re @@ -6,7 +8,6 @@ import re from docutils import nodes from sphinx import addnodes, util, builders from sphinx.locale import admonitionlabels - from urllib.request import url2pathname @@ -31,9 +32,8 @@ class BootstrapTranslator(nodes.NodeVisitor, object): html_title = 'html_title' html_subtitle = 'html_subtitle' - # tags - def __init__(self, builder, document): + def __init__(self, document, builder): # order of parameter swapped between Sphinx 1.x and 2.x, check if # we're running 1.x and swap back if not isinstance(builder, builders.Builder): @@ -42,10 +42,12 @@ class BootstrapTranslator(nodes.NodeVisitor, object): super(BootstrapTranslator, self).__init__(document) self.builder = builder self.meta = [ + # HTMLWriter strips out the first two items from Translator.meta + # with no explanation '', '', - '\n ', - '\n ' ] + self.add_meta('') + self.add_meta('') self.body = [] self.fragment = self.body self.html_body = self.body @@ -57,7 +59,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object): self.context = [] self.section_level = 0 - self.config = builder.config + self.config = self.builder.config self.highlightlang = self.highlightlang_base = self.builder.config.highlight_language self.highlightopts = getattr(builder.config, 'highlight_options', {}) @@ -67,7 +69,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object): self.param_separator = ',' def encode(self, text): - return text.translate({ + return str(text).translate({ ord('&'): u'&', ord('<'): u'<', ord('"'): u'"', @@ -79,7 +81,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object): self.meta.append('\n ' + meta) def starttag(self, node, tagname, **attributes): - tagname = tagname.lower() + tagname = str(tagname).lower() # extract generic attributes attrs = {name.lower(): value for name, value in attributes.items()} @@ -113,8 +115,8 @@ class BootstrapTranslator(nodes.NodeVisitor, object): ) # only "space characters" SPACE, CHARACTER TABULATION, LINE FEED, # FORM FEED and CARRIAGE RETURN should be collapsed, not al White_Space - def attval(self, value, whitespace=re.compile(u'[ \t\n\f\r]')): - return self.encode(whitespace.sub(u' ', str(value))) + def attval(self, value, whitespace=re.compile(u'[ \t\n\f\r]+')): + return self.encode(whitespace.sub(' ', str(value))) def astext(self): return u''.join(self.body) @@ -137,6 +139,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object): def visit_meta(self, node): if node.hasattr('lang'): node['xml:lang'] = node['lang'] + # del(node['lang']) meta = self.starttag(node, 'meta', **node.non_default_attributes()) self.add_meta(meta) def depart_meta(self, node): @@ -156,6 +159,11 @@ class BootstrapTranslator(nodes.NodeVisitor, object): if not self.section_level: self.body.append(u'') + def visit_topic(self, node): + self.body.append(self.starttag(node, 'nav')) + def depart_topic(self, node): + self.body.append(u'') + def is_compact_paragraph(self, node): parent = node.parent if isinstance(parent, (nodes.document, nodes.compound, @@ -197,6 +205,18 @@ class BootstrapTranslator(nodes.NodeVisitor, object): def depart_compact_paragraph(self, node): pass + def visit_problematic(self, node): + if node.hasattr('refid'): + self.body.append('' % node['refid']) + self.context.append('') + else: + self.context.append('') + self.body.append(self.starttag(node, 'span', CLASS='problematic')) + + def depart_problematic(self, node): + self.body.append('') + self.body.append(self.context.pop()) + def visit_literal_block(self, node): if node.rawsource != node.astext(): # most probably a parsed-literal block -- don't highlight @@ -215,7 +235,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object): else: opts = {} - def warner(msg): + def warner(msg, **kw): self.builder.warn(msg, (self.builder.current_docname, node.line)) highlighted = self.builder.highlighter.highlight_block( node.rawsource, lang, opts=opts, warn=warner, linenos=linenos, @@ -319,9 +339,9 @@ class BootstrapTranslator(nodes.NodeVisitor, object): def visit_title(self, node): parent = node.parent - closing = u'

    ' + closing = u'' if isinstance(parent, nodes.Admonition): - self.body.append(self.starttag(node, 'p', CLASS='alert-title')) + self.body.append(self.starttag(node, 'h3', CLASS='alert-title')) elif isinstance(node.parent, nodes.document): self.body.append(self.starttag(node, 'h1')) closing = u'' @@ -388,11 +408,11 @@ class BootstrapTranslator(nodes.NodeVisitor, object): "Unsupported alignment value \"%s\"" % node['align'], location=doc ) - attrs['style'] = '; '.join( - '%s:%s' % (name, node[name] + ('px' if re.match(r'^[0-9]+$', node[name]) else '')) - for name in ['width', 'height'] - if name in node - ) + elif 'align' in node.parent and node.parent['align'] == 'center': + # figure > image + attrs['class'] += ' center-block' + + # todo: explicit width/height/scale? self.body.append(self.starttag(node, 'img', **attrs)) def depart_image(self, node): pass def visit_figure(self, node): @@ -443,12 +463,7 @@ class BootstrapTranslator(nodes.NodeVisitor, object): tagname = 'th' else: tagname = 'td' - attrs = {} - if 'morerows' in node: - attrs['rowspan'] = node['morerows']+1 - if 'morecols' in node: - attrs['colspan'] = node['morecols']+1 - self.body.append(self.starttag(node, tagname, **attrs)) + self.body.append(self.starttag(node, tagname)) self.context.append(tagname) def depart_entry(self, node): self.body.append(u''.format(self.context.pop())) @@ -500,20 +515,6 @@ class BootstrapTranslator(nodes.NodeVisitor, object): self.body.append(self.starttag(node, 'a', **attrs)) def depart_reference(self, node): self.body.append(u'') - def visit_download_reference(self, node): - # type: (nodes.Node) -> None - if node.hasattr('filename'): - self.body.append( - '' % - posixpath.join(self.builder.dlpath, node['filename'])) - self.body.append(node.astext()) - self.body.append('') - raise nodes.SkipNode - else: - self.context.append('') - def depart_download_reference(self, node): - # type: (nodes.Node) -> None - self.body.append(self.context.pop()) def visit_target(self, node): pass def depart_target(self, node): pass def visit_footnote(self, node): @@ -659,11 +660,11 @@ class BootstrapTranslator(nodes.NodeVisitor, object): classes = env.metadata[ref].get('types', 'tutorials') classes += ' toc-single-entry' if not toc else ' toc-section' self.body.append(self.starttag(node, 'div', CLASS="row " + classes)) - self.body.append(u'

    ') + self.body.append(u'

    ') self.body.append(title if title else util.nodes.clean_astext(env.titles[ref])) - self.body.append(u'

    ') + self.body.append(u'

    ') - entries = [(title, ref)] if not toc else ((e[0], e[1]) for e in list(toc)[0]['entries']) + entries = [(title, ref)] if not toc else ((e[0], e[1]) for e in toc[0]['entries']) for subtitle, subref in entries: baseuri = self.builder.get_target_uri(node['parent'])