class Plugin(BasePlugin): name = "pystache" defaults = dict( path = ("templates",), extension = "mustache", encoding = "utf-8", partials = None, layout = None, ) def __init__(self, **options): super().__init__(**options) self.renderer = None def setup(self, app): super().setup(app) if isinstance(self.cfg.path, str): self.cfg.path = [self.cfg.path] self.cfg.path = [P.abspath(p) for p in self.cfg.path] self.renderer = Renderer(file_encoding=self.cfg.encoding, search_dirs=self.cfg.path, file_extension=self.cfg.extension, partials=self.cfg.partials) @coroutine def render(self, path, layout=None, *ctx, **kw): layout = self.cfg.layout if layout is None else layout if layout: kw["yield"] = self.renderer.render_name(path, *ctx, **kw) path = layout return self.renderer.render_name(path, *ctx, **kw)
class MustacheRenderer(BaseRenderer): def __init__(self, handler, search_dirs, caching=True): super(MustacheRenderer, self).__init__(handler) if caching: self.renderer = CachedRenderer( handler.application.cache, search_dirs=search_dirs) else: self.renderer = PystacheRenderer(search_dirs=search_dirs) def _default_template_variables(self, kwargs): super(MustacheRenderer, self)._default_template_variables(kwargs) kwargs['xsrf_form_html'] = self.handler.xsrf_form_html() def add_options_variables(self, kwargs): kwargs['class_options_debug_html'] = 'debug' \ if options.debug_html else '' kwargs['js_debug'] = 'true' \ if options.debug else 'false' for option in options._options: kwargs['option_' + option] = getattr(options, option) def render_string_template(self, string_template, **kwargs): self._default_template_variables(kwargs) self.add_options_variables(kwargs) return self.renderer.render(string_template, kwargs) def render(self, template_name, context=None, **kwargs): # template_name = "".join(template_name.split('.')[:-1]) self._default_template_variables(kwargs) self.add_options_variables(kwargs) kwargs['block_css'] = self.block_css kwargs['block_javascript'] = self.block_javascript return self.renderer.render_name( template_name, context or self.handler, **kwargs) def block_css(self, text, *args, **kwargs): css_includes = load_json(text) csses = [] for css_args in css_includes: csses.append(self.add_css(**css_args)) return "\n".join(csses) def block_javascript(self, text, *args, **kwargs): js_includes = load_json(text) jses = [] for js_args in js_includes: jses.append(self.add_javascript(**js_args)) return "\n".join(jses) def render_error(self, *args, **kwargs): kwargs['option_debug?'] = options.debug error_template = self.renderer.render_name( "error", self.handler, *args, **kwargs) return self.render("base", block_content=error_template)
def _render_template(self, template_name, template_data = None, partials = None): r = Renderer(search_dirs=[ROOT_PATH+"/static/template/"],partials=partials) template_data = self._add_in_default_data(template_data) return r.render_name(template_name, template_data)
def _render_template(self, template_name, template_data=None, partials=None): r = Renderer(search_dirs=[self._get_template_directory()], partials=partials) template_data = self._add_in_default_data(template_data) return r.render_name(template_name, template_data)
def _render_html(self, html_file): html_path = ROOT_PATH + "/static/" if self._host_type and self._host_type != "main": html_path += self._host_type + "/html/" else: html_path += "html/" r = Renderer(search_dirs=[html_path], file_extension="html") template_data = r.render_name(html_file) return template_data
def test_render_name(self): """Test the render_name() method.""" data_dir = get_data_path() renderer = Renderer(search_dirs=data_dir) actual = renderer.render_name("say_hello", to='foo') self.assertString(actual, "Hello, foo")
class PagePropertiesEditor: def __init__(self, pagePropertiesEditor, templates={}, confluence=None, pagePropertiesOrder=None, **kwargs): self.editor = pagePropertiesEditor self.templates = templates self.confluence = confluence self.order = None if 'order' in kwargs: self.order = kwargs['order'] if pagePropertiesOrder is not None: self.order = pagePropertiesOrder self.renderer = Renderer( search_dirs="{}/templates".format(dirname(__file__)), file_extension="mustache", ) for t in ['user', 'page', 'link', 'list', 'value']: self.renderer.load_template(t) self.userkeys = {} def userkey(self, name): "resolve username to userkey" if name not in self.userkeys: self.userkeys[name] = self.confluence.getUser(name)['userKey'] return self.userkeys[name] ELEM = re.compile( r'''(?: \[ ( ~(?P<user>[^\]]*?) | (?P<spacekey>\w+):(?P<title>[^\]]*?) | (?P<link>[^\]]*?) ) \] | (?P<datetime>\d\d\d\d-\d\d-\d\d(?:\s\d\d:\d\d(?::\d\d)?)?) ) ''', re.VERBOSE) def get_storage(self, key, value, templates=None): "get storage representation for value using templates" def render(name, **context): # try first, if there is a name-specific template for _name in ["{}-{}".format(key, name), name]: # first try local templates if _name in templates: return self.renderer.render(templates[_name], context) # try editor templates elif _name in self.templates: return self.renderer.render(self.templates[_name], context) # finally return the default template return self.renderer.render_name(name, context) logger.debug("value (%s): %s", value.__class__.__name__, value) if isinstance(value, list): values = [{ 'value': self.get_storage(key, v, templates).strip() } for v in value] return render('list', list=values) if isinstance(value, date): value = value.isoformat() if isinstance(value, datetime): value = value.strftime('%Y-%m-%d') def replacer(m): d = m.groupdict() if d['user']: return render('user', userkey=self.userkey(d['user'])) if d['spacekey']: return render('page', **d) if d['link']: if '|' in d['link']: caption, href = d['link'].split('|') else: caption, href = (d['link'], ) * 2 return render('link', caption=caption, href=href) if d['datetime']: return render('datetime', datetime=d['datetime']) if not isinstance(value, basestring): value = str(value) value = self.ELEM.sub(replacer, value) return render('value', value=value.strip()) def edit_prop(self, key, data, action): if not isinstance(action, dict): return self.get_storage(key, action, {}) if 'replace' in action: data = action['replace'] if 'remove' in action: values = action['remove'] if not isinstance(values, list): values = [values] if not isinstance(data, list): if values[0] == data: data = [] else: logger.debug("replace(%s): value %s not present", key, values[0]) else: for val in values: if val in data: data.remove(val) if 'add' in action: values = action['add'] if not isinstance(values, list): values = [values] if not isinstance(data, list): if not data: data = [] else: data = [data] data += values return self.get_storage(key, data, action.get('templates', {})) def edit(self, page=None): updated_keys = [] if page is not None: content = page['body']['storage']['value'] pageProperties = page['pageProperties'] else: with open(dirname(__file__) + '/templates/page-props.html', 'r') as f: content = f.read() pageProperties = {} editor = edit(content) s = "ac|structured-macro[ac|name=details] > ac|rich-text-body > table > tbody > tr" for row in editor(s): key = editor(row).find('th').text().strip() if key not in self.editor: continue updated_keys.append(key) action = self.editor[key] if action == 'delete': editor(row).remove() continue data = pageProperties.get(key, '') html_data = self.edit_prop(key, data, action) x = editor(row).find('td') #import rpdb2 ; rpdb2.start_embedded_debugger('foo') x.html(html_data) selector = "ac|structured-macro[ac|name=details] table tbody" order = self.order if order is None: order = self.editor.keys() for key in order: action = self.editor[key] if action == 'delete': continue if key not in updated_keys: html_data = self.edit_prop(key, '', action) tr = "<tr><th>{}</th><td>{}</td></tr>".format(key, html_data) editor(selector).append(tr) return editor.end_edit()
class StorageEditor: def __init__(self, confluence=None, templates=None, partials=None, actions=None): self.templates = templates self.partials = partials self.actions = get_list_data(actions) self.confluence = confluence self.renderer = Renderer( search_dirs="{}/templates".format(dirname(__file__)), file_extension="mustache", ) def edit(self, content): if isinstance(content, Page): page = content else: page = None if isinstance(content, (dict, Page)): if content.get('body'): content = content['body']['storage']['value'] else: content = '' try: Q = self.begin_edit(content) except XMLSyntaxError as e: if page is None: raise log.debug("error: %s", e) if re.match(r"Entity '.*?' not defined", str(e)): log.debug('matched') raise StandardError( "There are double-escaped HTML entities in page %(spacekey)s:%(title)s" % page) else: raise for action in self.actions: if 'data' in action: if 'template' in action: content = self.renderer.render_name( action['template'], action['data']) else: content = self.renderer.render(action['content'], action['data']) else: content = action.get('content') if content is not None and 'type' in content: if content['type'] == 'wiki': content = self.confluence.convertWikiToStorage(content) method = action.get('action', 'html') log.debug("content for %s: %s", method, content) if action.get('select'): selection = Q(action['select']) else: selection = Q log.debug("selection: %s", selection) #import rpdb2 ; rpdb2.start_embedded_debugger('foo') if content is None: getattr(selection, method)() else: getattr(selection, method)(content) log.debug("edited: %s", str(Q)) return self.end_edit() def begin_edit(self, content=None): if content is None: content = self.content self.pyquery = storage_query(content) return self.pyquery FIRST_OPENING_TAG = re.compile(r'^<root[^>]*>') LAST_CLOSING_TAG = re.compile(r'</root>$') def end_edit(self, pyquery=None): if pyquery is None: pyquery = self.pyquery #import rpdb2 ; rpdb2.start_embedded_debugger('foo') root = pyquery.root.getroot() data = str(pyquery.__class__([x for x in root])) return data
def _render_html(self, html_file): r = Renderer(search_dirs=[ROOT_PATH+"/static/html/"],file_extension="html") template_data = r.render_name(html_file) return template_data