changeset 2515:00480cf83fa1

template: added icon handling: 2 new methods can be used: - icon_defs to include definitions of svg icons - icon to use one previously declared svg plain svg is used instead of icon fonts to improve accessibility.
author Goffi <goffi@goffi.org>
date Sun, 11 Mar 2018 19:18:00 +0100
parents 4440ea7047bd
children 842bd1594077
files src/tools/common/template.py
diffstat 1 files changed, 36 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/tools/common/template.py	Fri Mar 02 17:53:31 2018 +0100
+++ b/src/tools/common/template.py	Sun Mar 11 19:18:00 2018 +0100
@@ -50,6 +50,7 @@
 
 from jinja2 import Markup as safe
 from jinja2 import is_undefined
+from lxml import etree
 
 HTML_EXT = ('html', 'xhtml')
 DEFAULT_LOCALE = u'en_GB'
@@ -221,6 +222,7 @@
         self.env.filters['highlight'] = self.highlight
         # custom tests
         self.env.tests['in_the_past'] = self._in_the_past
+        self.icons_path = os.path.join(host.media_dir, u'fonts/fontello/svg')
 
     def installTranslations(self):
         i18n_dir = os.path.join(self.base_dir, 'i18n')
@@ -567,9 +569,35 @@
         """
         return time.time() > int(timestamp)
 
+    ## template methods ##
+
+    def _icon_defs(self, *names):
+        """Define svg icons which will be used in the template, and use their name as id"""
+        svg_elt = etree.Element('svg', nsmap={None: 'http://www.w3.org/2000/svg'},
+                                width='0', height='0', style='display: block'
+                                )
+        defs_elt = etree.SubElement(svg_elt, 'defs')
+        for name in names:
+            path = os.path.join(self.icons_path, name + u'.svg')
+            icon_svg_elt = etree.parse(path).getroot()
+            # we use icon name as id, so we can retrieve them easily
+            icon_svg_elt.set('id', name)
+            if not icon_svg_elt.tag == '{http://www.w3.org/2000/svg}svg':
+                raise exceptions.DataError(u'invalid SVG element')
+            defs_elt.append(icon_svg_elt)
+        return safe(etree.tostring(svg_elt, encoding='unicode'))
+
+    def _icon_use(self, name, cls=''):
+        return safe(u"""<svg class="svg-icon{cls}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
+          <use href="#{name}"/>
+        </svg>
+        """.format(
+            name=name,
+            cls=(' ' + cls) if cls else ''))
+
     def render(self, template, theme=None, locale=DEFAULT_LOCALE, root_path=u'', media_path=u'', css_files=None, css_inline=False, **kwargs):
         """render a template
-
+.
         @param template(unicode): template to render (e.g. blog/articles.html)
         @param theme(unicode): template theme
         @param root_path(unicode): prefix of the path/URL to use for template root
@@ -603,6 +631,9 @@
         if css_files is None:
             css_files = self.getCSSFiles(template_path, template_root_dir)
 
+        kwargs['icon_defs'] = self._icon_defs
+        kwargs['icon'] = self._icon_use
+
         if css_inline:
             css_contents = []
             for css_file in css_files:
@@ -616,4 +647,7 @@
         self.setLocale(locale)
         # XXX: theme used in template arguments is the requested theme, which may differ from actual theme
         #      if the template doesn't exist in the requested theme.
-        return template_source.render(theme=theme, root_path=root_path, media_path=media_path, css_files=css_files, locale=self._locale, gidx=Indexer(), script=scripts_handler, **kwargs)
+        return template_source.render(theme=theme, root_path=root_path, media_path=media_path,
+                                      css_files=css_files, locale=self._locale,
+                                      gidx=Indexer(), script=scripts_handler,
+                                      **kwargs)