1 # -*- coding: utf-8 -*-
 
   3 # This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
 
   4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 
   7 from . import UnicodeException
 
   8 from .utils import extend_element
 
  11 class UnknownElement(UnicodeException):
 
  15 class Renderer(object):
 
  16     """ Renders an element in a context to some kind of container. """
 
  17     def render(self, element, ctx):
 
  18         """ Renders the element in the context. """
 
  21     def render_text(self, text, ctx):
 
  22         """ Renders the text in the context. """
 
  26 class TreeRenderer(Renderer):
 
  27     """ Renders insides as XML in a <_/> container. """
 
  30     def __init__(self, tag_name=None, attrib=None):
 
  31         self.tag_name = tag_name
 
  32         self.attrib = attrib or {}
 
  35         root = etree.Element(self.root_name)
 
  37             inner = etree.Element(self.tag_name, **self.attrib)
 
  43     def text_container(self):
 
  44         root = etree.Element(self.root_name)
 
  47     def subcontext(self, element, ctx):
 
  50     def get_insides(self, element, ctx):
 
  51         subctx = self.subcontext(element, ctx)
 
  53             yield self.render_text(element.text, ctx)
 
  56                 yield ctx.format.render(child, subctx)
 
  57             except UnknownElement:
 
  60                 yield self.render_text(child.tail, ctx)
 
  62     def render(self, element, ctx):
 
  63         root, inner = self.container()
 
  64         for inside in self.get_insides(element, ctx):
 
  65             extend_element(inner, inside)
 
  68     def render_text(self, text, ctx):
 
  69         root, inner = self.text_container()
 
  75 class Register(object):
 
  76     """ Class-renderer register.
 
  78     >>> from librarian.core import Div
 
  79     >>> renderer = Renderer()
 
  81     >>> reg.register(Div, 'a.b', renderer)
 
  82     >>> reg.get(Div, 'a.b.c') is renderer
 
  89     def register(self, tag, klass, renderer):
 
  90         self.classes[tag, klass] = renderer
 
  92     def get(self, tag, klass=None):
 
  95                 return self.classes[tag, klass]
 
  98                     klass = klass.rsplit('.', 1)[-2]
 
 102             return self.classes[tag, None]
 
 104             raise UnknownElement(tag)
 
 106     def get_for(self, element):
 
 107         return self.get(type(element), element.get('class'))