Source code for odoo_tools.modules.render

"""
Render Modules
==============

This module cover a series of function that can be used to render
the html description of the module based on static content and the
description string in the manifest.

This behaves in similar ways as how Odoo render the description
string for modules within Odoo.

You may want to render html description of the module when you need
to display the module description to Odoo users or potentially in a
web store.
"""
import lxml
import lxml.html

from docutils import nodes
from docutils.utils import Reporter
from docutils.core import publish_string
from docutils.transforms import Transform, writer_aux
from docutils.writers.html4css1 import Writer


[docs]class MyFilterMessages(Transform): """ Custom docutils transform to remove `system message` for a document and generate warnings. (The standard filter removes them based on some `report_level` passed in the `settings_override` dictionary, but if we use it, we can't see them and generate warnings.) """ default_priority = 870
[docs] def apply(self): for node in self.document.traverse(nodes.system_message): node.parent.remove(node)
[docs]class MyWriter(Writer): """ Custom docutils html4ccs1 writer that doesn't add the warnings to the output document. """
[docs] def get_transforms(self): return [MyFilterMessages, writer_aux.Admonitions]
[docs]def render_description_str(path, description=''): html_file = path / "static/description/index.html" if html_file.exists(): doc = html_file.open('rb').read() html = lxml.html.document_fromstring(doc) for element, attribute, link, pos in html.iterlinks(): # TODO convert to an actual url that can work # especially if the assets aren't loaded anywhere exactly if ( element.get('src') and '//' not in element.get('src') and 'static/' not in element.get('src') ): element.set( 'src', "/%s/static/description/%s" % ( path.name, element.get('src') ) ) return lxml.html.tostring(html).decode() readme_files = ['README.rst', 'README.md', 'README.txt'] for readme in readme_files: readme_path = path / readme if not readme_path.exists(): continue readme_data = readme_path.open().read() break else: readme_data = description overrides = { 'embed_stylesheet': False, 'doctitle_xform': False, 'output_encoding': 'unicode', 'xml_declaration': False, 'file_insertion_enabled': False, 'report_level': Reporter.ERROR_LEVEL } description_html = publish_string( source=readme_data, settings_overrides=overrides, writer=MyWriter() ) return description_html