def markdown(value): """Renders a string as Markdown. Syntax: {{ value|markdown }} We are using `markdown2 <https://pypi.python.org/pypi/markdown2>`_ to do the rendering. """ import markdown2 return Markup(markdown2.markdown(value))
def message_filter(ctx, value): # type: (Any, str) -> Union[str, Markup] """ Return slightly escaped log message to make it keep its formatting in HTML. * spaces are replaced with non-breakable spaces (`` ``); * new-line characters are replaced with ``<br/>`` elements. :param ctx: render context governed by Jinja. :param str value: message to escape. """ result = value.replace('\n', cast(str, Markup('<br/>\n'))).replace( ' ', cast(str, Markup(' '))) if ctx.autoescape: return Markup(result) return result
def markup_join(seq): """Concatenation that escapes if necessary and converts to unicode.""" buf = [] iterator = imap(soft_unicode, seq) for arg in iterator: buf.append(arg) if hasattr(arg, '__html__'): return Markup(u'').join(chain(buf, iterator)) return concat(buf)
def do_indent(s, width=4, first=False, blank=False, indentfirst=None): """Return a copy of the string with each line indented by 4 spaces. The first line and blank lines are not indented by default. :param width: Number of spaces to indent by. :param first: Don't skip indenting the first line. :param blank: Don't skip indenting empty lines. .. versionchanged:: 2.10 Blank lines are not indented by default. Rename the ``indentfirst`` argument to ``first``. """ if indentfirst is not None: warnings.warn(DeprecationWarning( 'The "indentfirst" argument is renamed to "first".'), stacklevel=2) first = indentfirst indention = u' ' * width newline = u'\n' if isinstance(s, Markup): indention = Markup(indention) newline = Markup(newline) s += newline # this quirk is necessary for splitlines method if blank: rv = (newline + indention).join(s.splitlines()) else: lines = s.splitlines() rv = lines.pop(0) if lines: rv += newline + newline.join(indention + line if line else line for line in lines) if first: rv = indention + rv return rv
def publisher_small(reuse, size=100, lang=DEFAULT_LANG): from weckan.model import User from ckanext.youckan.models import ReuseAsOrganization markup = ( '<a class="avatar" href="{url}" title="{title}">' '{avatar}' '</a>' '<a class="user" href="{url}" title="{title}">' '{title}' '</a>' ) organization = ReuseAsOrganization.get_org(reuse) if organization: org_url = url(lang, 'organization', organization.name) logo = '<img src="{0}" alt="{1} logo" />'.format(organization.image_url, organization.display_name) return Markup(markup.format(url=org_url, avatar=logo, title=organization.display_name)) else: user = User.get(reuse.owner_id) user_url = '{0}/u/{1}/'.format(conf['sso_url'], user.name) return Markup(markup.format(url=user_url, avatar=avatar(user, size), title=user.fullname))
def format_message_explicit_emotes(message, emotes, size="1", cheer=False): if not emotes: return Markup(format_message_cheer(message, size=size, cheer=cheer)) # emotes format is # <emoteid>:<start>-<end>[,<start>-<end>,...][/<emoteid>:<start>-<end>,.../...] # eg: # 123:0-2/456:3-6,7-10 # means that chars 0-2 (inclusive, 0-based) are emote 123, # and chars 3-6 and 7-10 are two copies of emote 456 parsed_emotes = [] for emote in emotes.split('/'): emoteid, positions = emote.split(':') emoteid = int(emoteid) for position in positions.split(','): start, end = position.split('-') start = int(start) end = int( end ) + 1 # make it left-inclusive, to be more consistent with how Python does things parsed_emotes.append((start, end, emoteid)) parsed_emotes.sort(key=lambda x: x[0]) bits = [] prev = 0 for start, end, emoteid in parsed_emotes: if prev < start: bits.append( format_message_cheer(message[prev:start], size=size, cheer=cheer)) url = escape("https://static-cdn.jtvnw.net/emoticons/v1/%d/%s.0" % (emoteid, size)) command = escape(message[start:end]) bits.append('<img src="%s" alt="%s" title="%s">' % (url, command, command)) prev = end if prev < len(message): bits.append( format_message_cheer(message[prev:], size=size, cheer=cheer)) return Markup(''.join(bits))
def jinja_x5_encode(d): """Jinja filter to encode a template variable to JSON+base64.""" try: return Markup( b64encode( json.dumps(d, ensure_ascii=True, default=json_default, encoding='utf-8'))) except (TypeError, ValueError): logger.exception('Error converting template variable to json') return ''
def dateformat(value, formatstring='%Y-%m-%d', nonchar=''): """Formates a date. Tries to convert the given ``value`` to a ``date`` object and then formats it according to ``formatstring``:: {{ date.today()|dateformat }} {{ "20171224"|dateformat('%Y-%W') }} """ if not value: return nonchar return Markup( convert_to_date(value).strftime(formatstring).replace('-', '‑'))
def file_content_filter(ctx, value): # type: (Any, str) -> Union[str, Markup] # pylint: disable=unused-argument """ Return content of the given file. File path must be relative to an assets directory set by ``--assets`` option. :param ctx: render context governed by Jinja. :param str value: path to a file to include. """ with io.open(os.path.join(ctx['ARGS'].assets, value), 'r') as f: return Markup(f.read())
def seguir(obraid): emailto = "" obra = fromcache("obra-" + obraid) or tocache("obra-" + obraid, _get_obras(obraid=obraid)[0]) if not obra: print "Não achou a obra!" return abort(404) slug = obra['slug'] if request.form: follow = UserFollow() if authapi.is_authenticated(): follow.user = authapi.authenticated_user() emailto = follow.user.email follow.obra_id = int(obraid) if request.form.has_key('faceid'): follow.facebook_id = request.form['faceid'] if request.form.has_key('twitterid'): follow.twitter_id = request.form['twitterid'] if request.form.has_key('email'): follow.email = request.form['email'] emailto = follow.email dbsession.commit() if emailto: base_url = current_app.config['BASE_URL'] base_url = base_url if base_url[ -1:] != '/' else base_url[:-1] #corta a barra final _dados_email = { 'titulo': obra['title'], 'link': base_url + url_for('.obra', slug=slug), 'descricao': Markup(obra['content']).striptags(), 'monitore_url': base_url + url_for('.index'), 'siteurl': base_url, } sendmail(current_app.config['SEGUIROBRA_SUBJECT'] % _dados_email, emailto, current_app.config['SEGUIROBRA_MSG'] % _dados_email) return dumps({'status': 'ok'}) else: return dumps({'status': 'error'})
def script_tag(filename, **kwargs): """Generates an HTML `script` tag. Files are service from `js` subdirectory in the static folder """ filename = "js/%s" % filename if not filename.endswith('.js'): filename += '.js' kwargs['src'] = static_file(filename) kwargs['type'] = "text/javascript" return Markup("<script %s></script>" % _format_attr(**kwargs))
def component_html(path, *args, **kwargs): try: from jinja2.utils import Markup except ImportError: Markup = None # todo: replace with importlib import cli2 ComponentCls = cli2.Node(path).target component = ComponentCls(*args, **kwargs) html = component.to_html() if Markup: html = Markup(html) return mark_safe(html)
def render(self, template_name): medias = [] media_cls = getattr(self, 'Media') if hasattr(media_cls, 'js'): for script in media_cls.js: medias.append('<script src="{}"></script>'.format(script)) if hasattr(media_cls, 'css'): for css_media, urls in media_cls.css.items(): for url in urls: js = '$("<link/>", {{rel: "stylesheet",type: "text/css",href: "{}"}}).appendTo("head");' js = js.format(url) medias.append('<script>{}</script>'.format(js)) html = render_to_string(template_name, {'component': self}) return Markup('{}\n{}'.format(''.join(medias), html))
def component_html(path, *args, **kwargs): from django.utils.safestring import mark_safe try: from jinja2.utils import Markup except ImportError: Markup = None import cli2 ComponentCls = cli2.Node.factory(path).target component = ComponentCls(*args, **kwargs) html = component.to_html() if Markup: html = Markup(html) return mark_safe(html)
def utm_args(value, link_name, user_id=None): from flask import current_app # if current_app.config['DEBUG'] or current_app.config['STAGING']: # return value if value is None: return value value = unicode(value) last_symbol = value[-1] if value else '' suffix = u"" if '#' in value: try: value, suffix = value.split('#') suffix = "#" + suffix if suffix else "" except Exception: return value if user_id: return Markup("%s%s%s" % (value, '&' if last_symbol not in '&?' else '', "utm_source=%s&utm_medium=email&utm_term=%s%s" % (link_name, user_id, suffix))) return Markup("%s%s%s" % (value, '&' if last_symbol not in '&?' else '', "utm_source=%s&utm_medium=email%s" % (link_name, suffix)))
def edit_shard(request): shard = request.context shardform = Form(schema.Shard(), buttons=('submit', )) if 'submit' in request.POST: controls = request.POST.items() try: appstruct = shardform.validate(controls) shard.name = appstruct['name'] shard.url = appstruct['url'] shard.selector = appstruct['selector'] shard.width = appstruct['width'] shard.height = appstruct['height'] shard.triggers = appstruct['triggers'] except ValidationFailure, e: return {'form': Markup(e.render())}
def otag(obj): """Link like this: `<a href="obj.url">obj.designator</a>`.""" if not getattr(obj, 'url'): return link = obj.url designator = obj.designator style = '' klass = '' # # wir machen ein bischen intelligente Formatierung hier # # TODO: inaktiv und erledigt und storniert unterscheiden # if getattr(obj, 'erledigt', False): # style = '' # klass = 'class="cs_erledigt"' return Markup('<a href="{}" {} {}>{}</a>'.format( link, style, klass, jinja2.escape(designator)))
def style_tag(filename, **kwargs): """Generates an HTML `link` tag to a CSS stylesheet file. The extension '.css' is added by default if missing. Files are served from the `css` subdirectory in the static folder. """ filename = "css/%s" % filename if not filename.endswith('.css'): filename += '.css' kwargs["rel"] = "stylesheet" kwargs["type"] = "text/css" kwargs["href"] = static_file(filename) return Markup("<link %s/>" % _format_attr(**kwargs))
def do_urlize(environment, value, trim_url_limit=None, nofollow=False): """Converts URLs in plain text into clickable links. If you pass the filter an additional integer it will shorten the urls to that number. Also a third argument exists that makes the urls "nofollow": .. sourcecode:: jinja {{ mytext|urlize(40, true) }} links are shortened to 40 chars and defined with rel="nofollow" """ rv = urlize(soft_unicode(value), trim_url_limit, nofollow) if environment.autoescape: rv = Markup(rv) return rv
def authors(value): if len(value) > 2: authors = '%s; %s' % (value[0], value[1]) html = '<ul class="dropdown"><li>%s; et al.<ul>' % authors for i in range(len(value) - 2): html += '<li>%s<li>' % value[i + 2] html += '</ul></li></ul>' else: if len(value) == 2: authors = '%s; %s' % (value[0], value[1]) elif len(value) == 1: authors = value[0] elif len(value) == 0: authors = 'Not Available' html = '<p>%s</p>' % authors return Markup(html)
def edit_slideshow_POST(request): slideshow = request.context form = Form(schema.Slideshow(), buttons=('submit', )) controls = request.POST.items() try: for slide in slideshow.slides: request.db.delete(slide) slideshow.slides = [] appstruct = form.validate(controls) slideshow.name = appstruct['name'] for i, data in enumerate(appstruct['slides']): slide = tables.Slide(duration=data['duration'], shard_id=data['shard'], order=i) slideshow.slides.append(slide) return HTTPSeeOther(location=request.url) except ValidationFailure, e: return {'form': Markup(e.render()), 'title': 'Edit Slideshow'}
def formaturl(url, title=None): if not url: return '' if title is None: title = url parsed = urlparse(url) if parsed.scheme == 'http' or parsed.scheme == 'https': url = Markup.escape(url) title = Markup.escape(title) title = unicode(title).replace( '*', '<span class="censored">*</span>').replace( u'\u2026', u'<span class="censored">\u2026</span>') return Markup('<a href="%(url)s">%(title)s</a>' % { 'url': url, 'title': title }) else: return url
def authorize(ctx, value, permission_types, tag=None): """Display content only if the current logged in user has a specific permission. This means if all strings in `permission_types` occur in `credential.permissions`. """ if not isinstance(permission_types, list): permission_types = [permission_types] if tag is None: tag = 'span' m = re.search(r'$\s*<(%s)' % '|'.join(NOTAGS), value) if m: tag = '' else: m = re.search(r'<(%s)' % '|'.join(BLOCKTAGS), value) if m: tag = 'div' # Permissions disabled -> granted granted = ctx.get('request').get('_gaetk_disable_permissions', False) for permission in permission_types: if ctx.get('credential') and permission in ctx.get( 'credential').permissions: granted = True break if granted: if not tag: return value value = '<{tag} class="gaetk_restricted">{value}</{tag}>'.format( tag=tag, value=jinja2.escape(value)) else: if not ctx.get('credential'): logger.info('context has no credential!') if not tag: value = '…<!-- Berechtigung %s -->' % (', '.join(permission_types)) else: value = '<{tag} class="gaetk_restricted_denied"><!-- !Berechtigung {perm} --></{tag}>'.format( tag=tag, perm=', '.join(permission_types)) if ctx.eval_ctx.autoescape: return Markup(value) return value
def new_slideshow(request): shardform = Form(schema.Slideshow(), buttons=('submit', )) if 'submit' in request.POST: controls = request.POST.items() try: appstruct = shardform.validate(controls) slideshow = tables.Slideshow(name=appstruct['name']) for i, data in enumerate(appstruct['slides']): slide = tables.Slide(duration=data['duration'], shard_id=data['shard'], order=i) slideshow.slides.append(slide) request.db.add(slideshow) request.db.flush() location = u"%s/shows/%d/edit" % \ (request.application_url, slideshow.id) return HTTPSeeOther(location=location) except ValidationFailure, e: return {'form': Markup(e.render())}
class TemplateModule(object): """Represents an imported template. All the exported names of the template are available as attributes on this object. Additionally converting it into an unicode- or bytestrings renders the contents. """ def __init__(self, template, context): self._body_stream = list(template.root_render_func(context)) self.__dict__.update(context.get_exported()) self.__name__ = template.name __unicode__ = lambda x: concat(x._body_stream) __html__ = lambda x: Markup(concat(x._body_stream)) def __str__(self): return unicode(self).encode('utf-8') def __repr__(self): if self.__name__ is None: name = 'memory:%x' % id(self) else: name = repr(self.__name__) return '<%s %s>' % (self.__class__.__name__, name)
def new_shard(request): shardform = Form(schema.Shard(), buttons=('submit', )) if 'submit' in request.POST: controls = request.POST.items() try: appstruct = shardform.validate(controls) newshard = tables.Shard( name=appstruct['name'], url=appstruct['url'], selector=appstruct['selector'], width=appstruct['width'], height=appstruct['height'], triggers=appstruct['triggers'], ) request.db.add(newshard) request.db.flush() location = u"%s/shards/%d/edit" % \ (request.application_url, newshard.id) log.debug(u"new shard at %s", location) return HTTPSeeOther(location) except ValidationFailure, e: return {'form': Markup(e.render())}
def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False, target=None, rel=None): """Converts URLs in plain text into clickable links. If you pass the filter an additional integer it will shorten the urls to that number. Also a third argument exists that makes the urls "nofollow": .. sourcecode:: jinja {{ mytext|urlize(40, true) }} links are shortened to 40 chars and defined with rel="nofollow" If *target* is specified, the ``target`` attribute will be added to the ``<a>`` tag: .. sourcecode:: jinja {{ mytext|urlize(40, target='_blank') }} .. versionchanged:: 2.8+ The *target* parameter was added. """ policies = eval_ctx.environment.policies rel = set((rel or '').split() or []) if nofollow: rel.add('nofollow') rel.update((policies['urlize.rel'] or '').split()) if target is None: target = policies['urlize.target'] rel = ' '.join(sorted(rel)) or None rv = urlize(value, trim_url_limit, rel=rel, target=target) if eval_ctx.autoescape: rv = Markup(rv) return rv
def urlize(ctx, text, trim_url_limit=None, rel=None, target=None): """Converts any URLs in text into clickable links. Works on http://, https:// and www. links. Links can have trailing punctuation (periods, commas, close-parens) and leading punctuation (opening parens) and it'll still do the right thing. Aditionally it will populate the input with application context related links linke issues and groups. If trim_url_limit is not None, the URLs in link text will be limited to trim_url_limit characters. If nofollow is True, the URLs in link text will get a rel="nofollow" attribute. If target is not None, a target attribute will be added to the link. """ words = _word_split_re.split(escape(text)) for i, word in enumerate(words): match = _punctuation_re.match(word) if match: lead, word, trail = match.groups() word = sub('({})'.format(cve_id_regex), '<a href="/\\1" rel="noopener">\\1</a>', word) word = sub('({})'.format(vulnerability_group_regex), '<a href="/\\1" rel="noopener">\\1</a>', word) words[i] = '{}{}{}'.format(lead, word, trail) text = ''.join(words) if ctx.autoescape: text = Markup(text) text = do_urlize(ctx, text, trim_url_limit=trim_url_limit, target=target, rel=rel) return text
def publisher_avatar(user, organization, size=100, **kwargs): if organization: org_url = url('organization', organization.name) image_url = organization.image_url or static('/img/placeholder_producer.png') content = ( '<a class="organization" href="{url}" title="{display}">' '<img src="{image_url}" alt="{display}"/>' '</a>' ).format(display=organization.display_name, url=org_url, image_url=image_url, size=size) else: user_url = '{0}/u/{1}/'.format(conf['sso_url'], user.name) content = ( '<a class="{clazz}" href="{url}" title="{display}">' '<img src="{url}/avatar/" alt="{display}"/>' '</a>' ).format(clazz='', display=user.fullname, url=user_url, size=size) classes = [] if kwargs.get('overwrite') else ['publisher-avatar-{0}'.format(size)] classes.extend([cls for cls in kwargs.get('classes', '').split()]) return Markup( '<div class="{classes}">' '<div class="frame">{content}</div>' '</div>'.format(classes=' '.join(classes), content=content) )
def select_multi_checkbox(field: Field, **kwargs: Any) -> str: html = ["<ul {}>".format(html_params(id=field.id, class_="multi-select"))] show_other = False for value, label, _ in field.iter_choices(): if value == "OTHER": show_other = True continue field_id = f"{field.id}-{value}" options = dict(kwargs, type="checkbox", name=field.name, value=value, id=field_id) if value in (field.data or ()): options["checked"] = "checked" html.append("<li><input %s /> " % html_params(**options)) html.append('<label for="%s">%s</label></li>' % (field_id, label)) if show_other: data = field.data or () all_choices = set(value for value, _, _ in field.iter_choices()) other_value = [v for v in data if v not in all_choices] other_value = other_value[0] if other_value else "" other_id = f"{field_id}-{value}" options = dict(kwargs, type="text", name=field.name, value=other_value, id=other_id) html.append( f'<li class="other"><label for="{field_id}">{label}:</label> ') html.append("<input %s /></li>" % html_params(**options)) html.append("</ul>") return Markup("".join(html))