def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=["jinja2.ext.autoescape", "jinja2.ext.with_"], loader=jinja2.FileSystemLoader(os.path.join(self.root_path, "templates")), ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter(lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter(lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] if load_plugins: self.load_plugins()
def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( os.path.join(self.root_path, 'templates'))) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter( lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] if load_plugins: self.load_plugins()
def on_setup_env(self, **extra): maybeasset = jinja2.contextfilter( lambda ctx, *a, **kw: maybeasset_filter(*a, **kw)) self.env.jinja_env.filters["maybeasset"] = maybeasset maybeurl = jinja2.contextfilter( lambda ctx, *a, **kw: maybeurl_filter(*a, **kw)) self.env.jinja_env.filters["maybeurl"] = maybeurl
def __init__(self, *args, **kwargs): JinjaGenerator.__init__(self, *args, **kwargs) self.environment.filters.update( feature=lambda x: 'feature = "{}"'.format(x), enum_type=jinja2.contextfilter(lambda ctx, enum: enum_type(enum, ctx['feature_set'])), enum_value=jinja2.contextfilter(lambda ctx, enum: enum_value(enum, ctx['feature_set'])), type=to_rust_type, params=to_rust_params, identifier=identifier, no_prefix=jinja2.contextfilter(lambda ctx, value: strip_specification_prefix(value, ctx['spec'])) )
def __init__(self, *args, **kwargs): JinjaGenerator.__init__(self, *args, **kwargs) self._headers = dict() self.environment.globals.update( get_debug_impl=get_debug_impl, loadable=loadable, enum_member=enum_member, chain=itertools.chain ) self.environment.filters.update( defined=lambda x: 'defined({})'.format(x), type_to_c=type_to_c, params_to_c=params_to_c, param_names=param_names, pfn=pfn, ctx=ctx, no_prefix=jinja2.contextfilter(lambda ctx, value: strip_specification_prefix(value, ctx['spec'])), c_commands=c_commands ) self.environment.tests.update( supports=lambda x, arg: x.supports(arg), void=is_void, )
def __init__(self, root_path): self.root_path = os.path.abspath(root_path) self.config_filename = os.path.join(self.root_path, 'site.ini') self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( os.path.join(self.root_path, 'templates')) ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, )
def wrapper(fn): fn = _inject(fn, inject) if safe: fn = _make_safe(fn) if pass_context: fn = jinja2.contextfilter(fn) self._defer(lambda app: app.add_template_filter(fn, name=name)) return fn
def __init__(self, project): self.project = project self.root_path = os.path.abspath(project.tree) self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( os.path.join(self.root_path, 'templates')) ) from lektor.db import F self.jinja_env.filters.update( tojson=tojson_filter, # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(get_asset_url(*a, **kw))), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_random_id=lambda: uuid.uuid4().hex, ) from lektor.types import builtin_types self.types = builtin_types.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {}
def __init__(self, environment): super(CoreExtension, self).__init__(environment) self.environment.globals.update({ 'svg_icon': svg_icon, }) self.environment.filters.update({ 'richtext_isempty': richtext_isempty, 'slugify_unique': contextfilter(slugify_unique), })
def __init__(self, environment): super(CoreExtension, self).__init__(environment) self.environment.globals.update({ 'signed_redirect': signed_redirect, 'unsigned_redirect': unsigned_redirect, 'svg_icon': svg_icon, }) self.environment.filters.update({ 'slugify_unique': contextfilter(slugify_unique), })
def _register_options(self): # Add Context Functions for name, method in self.context_functions.items(): self._env.globals[name] = jinja2.contextfunction(method) # Add Context Filters for name, method in self.context_filters.items(): self._env.filters[name] = jinja2.contextfilter(method) # Add Filters for name, method in self.filters.items(): self._env.filters[name] = method # Add Tests for name, method in self.tests.items(): self._env.tests[name] = method
def __init__(self, project, load_plugins=True): self.project = project self.root_path = os.path.abspath(project.tree) self.theme_paths = [os.path.join(self.root_path, 'themes', theme) for theme in self.project.themes] if not self.theme_paths: # load the directories in the themes directory as the themes try: for fname in os.listdir(os.path.join(self.root_path, 'themes')): f = os.path.join(self.root_path, 'themes', fname) if os.path.isdir(f): self.theme_paths.append(f) except OSError: pass template_paths = [os.path.join(path, 'templates') for path in [self.root_path] + self.theme_paths] self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'], loader=jinja2.FileSystemLoader( template_paths) ) from lektor.db import F, get_alts self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter( lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter( lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_alts=get_alts, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] self.virtual_sources = {} if load_plugins: self.load_plugins() from lektor.db import siblings_resolver self.virtualpathresolver('siblings')(siblings_resolver)
def _register(self): django_jinja.library.filter( name=self.name, fn=jinja2.contextfilter(self))
def __init__(self, hass, limited=False): """Initialise template environment.""" super().__init__(undefined=jinja2.make_logging_undefined( logger=_LOGGER)) self.hass = hass self.template_cache = weakref.WeakValueDictionary() self.filters["round"] = forgiving_round self.filters["multiply"] = multiply self.filters["log"] = logarithm self.filters["sin"] = sine self.filters["cos"] = cosine self.filters["tan"] = tangent self.filters["asin"] = arc_sine self.filters["acos"] = arc_cosine self.filters["atan"] = arc_tangent self.filters["atan2"] = arc_tangent2 self.filters["sqrt"] = square_root self.filters["as_timestamp"] = forgiving_as_timestamp self.filters["as_local"] = dt_util.as_local self.filters["timestamp_custom"] = timestamp_custom self.filters["timestamp_local"] = timestamp_local self.filters["timestamp_utc"] = timestamp_utc self.filters["to_json"] = to_json self.filters["from_json"] = from_json self.filters["is_defined"] = fail_when_undefined self.filters["max"] = max self.filters["min"] = min self.filters["random"] = random_every_time self.filters["base64_encode"] = base64_encode self.filters["base64_decode"] = base64_decode self.filters["ordinal"] = ordinal self.filters["regex_match"] = regex_match self.filters["regex_replace"] = regex_replace self.filters["regex_search"] = regex_search self.filters["regex_findall_index"] = regex_findall_index self.filters["bitwise_and"] = bitwise_and self.filters["bitwise_or"] = bitwise_or self.filters["ord"] = ord self.globals["log"] = logarithm self.globals["sin"] = sine self.globals["cos"] = cosine self.globals["tan"] = tangent self.globals["sqrt"] = square_root self.globals["pi"] = math.pi self.globals["tau"] = math.pi * 2 self.globals["e"] = math.e self.globals["asin"] = arc_sine self.globals["acos"] = arc_cosine self.globals["atan"] = arc_tangent self.globals["atan2"] = arc_tangent2 self.globals["float"] = forgiving_float self.globals["as_local"] = dt_util.as_local self.globals["as_timestamp"] = forgiving_as_timestamp self.globals["relative_time"] = relative_time self.globals["timedelta"] = timedelta self.globals["strptime"] = strptime self.globals["urlencode"] = urlencode if hass is None: return # We mark these as a context functions to ensure they get # evaluated fresh with every execution, rather than executed # at compile time and the value stored. The context itself # can be discarded, we only need to get at the hass object. def hassfunction(func): """Wrap function that depend on hass.""" @wraps(func) def wrapper(*args, **kwargs): return func(hass, *args[1:], **kwargs) return contextfunction(wrapper) self.globals["device_entities"] = hassfunction(device_entities) self.filters["device_entities"] = contextfilter( self.globals["device_entities"]) if limited: # Only device_entities is available to limited templates, mark other # functions and filters as unsupported. def unsupported(name): def warn_unsupported(*args, **kwargs): raise TemplateError( f"Use of '{name}' is not supported in limited templates" ) return warn_unsupported hass_globals = [ "closest", "distance", "expand", "is_state", "is_state_attr", "state_attr", "states", "utcnow", "now", ] hass_filters = ["closest", "expand"] for glob in hass_globals: self.globals[glob] = unsupported(glob) for filt in hass_filters: self.filters[filt] = unsupported(filt) return self.globals["expand"] = hassfunction(expand) self.filters["expand"] = contextfilter(self.globals["expand"]) self.globals["closest"] = hassfunction(closest) self.filters["closest"] = contextfilter(hassfunction(closest_filter)) self.globals["distance"] = hassfunction(distance) self.globals["is_state"] = hassfunction(is_state) self.globals["is_state_attr"] = hassfunction(is_state_attr) self.globals["state_attr"] = hassfunction(state_attr) self.globals["states"] = AllStates(hass) self.globals["utcnow"] = hassfunction(utcnow) self.globals["now"] = hassfunction(now)
def __init__(self, project, load_plugins=True, extra_flags=None): self.project = project self.root_path = os.path.abspath(project.tree) self.theme_paths = [ os.path.join(self.root_path, 'themes', theme) for theme in self.project.themes ] if not self.theme_paths: # load the directories in the themes directory as the themes try: for fname in os.listdir(os.path.join(self.root_path, 'themes')): f = os.path.join(self.root_path, 'themes', fname) if os.path.isdir(f): self.theme_paths.append(f) except OSError: pass template_paths = [ os.path.join(path, 'templates') for path in [self.root_path] + self.theme_paths ] self.jinja_env = CustomJinjaEnvironment( autoescape=self.select_jinja_autoescape, extensions=[ 'jinja2.ext.autoescape', 'jinja2.ext.with_', 'jinja2.ext.do' ], loader=jinja2.FileSystemLoader(template_paths)) from lektor.db import F, get_alts self.jinja_env.filters.update( tojson=tojson_filter, latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs), longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs), latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x), # By default filters need to be side-effect free. This is not # the case for this one, so we need to make it as a dummy # context filter so that jinja2 will not inline it. url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)), asseturl=jinja2.contextfilter( lambda ctx, *a, **kw: get_asset_url(*a, **kw)), markdown=jinja2.contextfilter( lambda ctx, *a, **kw: Markdown(*a, **kw)), ) self.jinja_env.globals.update( F=F, url_to=url_to, site=site_proxy, config=config_proxy, bag=lookup_from_bag, get_alts=get_alts, get_random_id=lambda: uuid.uuid4().hex, ) self.jinja_env.filters.update( datetimeformat=_pass_locale(dates.format_datetime), dateformat=_pass_locale(dates.format_date), timeformat=_pass_locale(dates.format_time), ) from lektor.types import builtin_types self.types = builtin_types.copy() from lektor.publisher import builtin_publishers self.publishers = builtin_publishers.copy() # The plugins that are loaded for this environment. This is # modified by the plugin controller and registry methods on the # environment. self.plugin_controller = PluginController(self, extra_flags) self.plugins = {} self.plugin_ids_by_class = {} self.build_programs = [] self.special_file_assets = {} self.special_file_suffixes = {} self.custom_url_resolvers = [] self.custom_generators = [] self.virtual_sources = {} if load_plugins: self.load_plugins() from lektor.db import siblings_resolver self.virtualpathresolver('siblings')(siblings_resolver)
def _register(self): django_jinja.library.filter(name=self.name, fn=jinja2.contextfilter(self))
def get_localtime_wrapper(conversion_wrapper): def localtime_wrapper(context, value, *args, **kwargs): value = template_localtime(value, use_tz=context.use_tz) return conversion_wrapper(value, *args, **kwargs) return contextfilter(localtime_wrapper)
def register_filter(func, name=None, ctx=False): name = name or func.__name__ if ctx: func = contextfilter(func) JINJA_FILTERS[name] = func
def __init__(self, hass): """Initialise template environment.""" super().__init__() self.hass = hass self.filters['round'] = forgiving_round self.filters['multiply'] = multiply self.filters['log'] = logarithm self.filters['sin'] = sine self.filters['cos'] = cosine self.filters['tan'] = tangent self.filters['sqrt'] = square_root self.filters['as_timestamp'] = forgiving_as_timestamp self.filters['timestamp_custom'] = timestamp_custom self.filters['timestamp_local'] = timestamp_local self.filters['timestamp_utc'] = timestamp_utc self.filters['is_defined'] = fail_when_undefined self.filters['max'] = max self.filters['min'] = min self.filters['random'] = random_every_time self.filters['base64_encode'] = base64_encode self.filters['base64_decode'] = base64_decode self.filters['ordinal'] = ordinal self.filters['regex_match'] = regex_match self.filters['regex_replace'] = regex_replace self.filters['regex_search'] = regex_search self.filters['regex_findall_index'] = regex_findall_index self.filters['bitwise_and'] = bitwise_and self.filters['bitwise_or'] = bitwise_or self.globals['log'] = logarithm self.globals['sin'] = sine self.globals['cos'] = cosine self.globals['tan'] = tangent self.globals['sqrt'] = square_root self.globals['pi'] = math.pi self.globals['tau'] = math.pi * 2 self.globals['e'] = math.e self.globals['float'] = forgiving_float self.globals['now'] = dt_util.now self.globals['utcnow'] = dt_util.utcnow self.globals['as_timestamp'] = forgiving_as_timestamp self.globals['relative_time'] = dt_util.get_age self.globals['strptime'] = strptime if hass is None: return # We mark these as a context functions to ensure they get # evaluated fresh with every execution, rather than executed # at compile time and the value stored. The context itself # can be discarded, we only need to get at the hass object. def hassfunction(func): """Wrap function that depend on hass.""" @wraps(func) def wrapper(*args, **kwargs): return func(hass, *args[1:], **kwargs) return contextfunction(wrapper) self.globals['expand'] = hassfunction(expand) self.filters['expand'] = contextfilter(self.globals['expand']) self.globals['closest'] = hassfunction(closest) self.filters['closest'] = contextfilter(hassfunction(closest_filter)) self.globals['distance'] = hassfunction(distance) self.globals['is_state'] = hassfunction(is_state) self.globals['is_state_attr'] = hassfunction(is_state_attr) self.globals['state_attr'] = hassfunction(state_attr) self.globals['states'] = AllStates(hass)
def __init__(self, hass): """Initialise template environment.""" super().__init__() self.hass = hass self.filters["round"] = forgiving_round self.filters["multiply"] = multiply self.filters["log"] = logarithm self.filters["sin"] = sine self.filters["cos"] = cosine self.filters["tan"] = tangent self.filters["asin"] = arc_sine self.filters["acos"] = arc_cosine self.filters["atan"] = arc_tangent self.filters["atan2"] = arc_tangent2 self.filters["sqrt"] = square_root self.filters["as_timestamp"] = forgiving_as_timestamp self.filters["timestamp_custom"] = timestamp_custom self.filters["timestamp_local"] = timestamp_local self.filters["timestamp_utc"] = timestamp_utc self.filters["is_defined"] = fail_when_undefined self.filters["max"] = max self.filters["min"] = min self.filters["random"] = random_every_time self.filters["base64_encode"] = base64_encode self.filters["base64_decode"] = base64_decode self.filters["ordinal"] = ordinal self.filters["regex_match"] = regex_match self.filters["regex_replace"] = regex_replace self.filters["regex_search"] = regex_search self.filters["regex_findall_index"] = regex_findall_index self.filters["bitwise_and"] = bitwise_and self.filters["bitwise_or"] = bitwise_or self.filters["ord"] = ord self.globals["log"] = logarithm self.globals["sin"] = sine self.globals["cos"] = cosine self.globals["tan"] = tangent self.globals["sqrt"] = square_root self.globals["pi"] = math.pi self.globals["tau"] = math.pi * 2 self.globals["e"] = math.e self.globals["asin"] = arc_sine self.globals["acos"] = arc_cosine self.globals["atan"] = arc_tangent self.globals["atan2"] = arc_tangent2 self.globals["float"] = forgiving_float self.globals["now"] = dt_util.now self.globals["utcnow"] = dt_util.utcnow self.globals["as_timestamp"] = forgiving_as_timestamp self.globals["relative_time"] = dt_util.get_age self.globals["strptime"] = strptime if hass is None: return # We mark these as a context functions to ensure they get # evaluated fresh with every execution, rather than executed # at compile time and the value stored. The context itself # can be discarded, we only need to get at the hass object. def hassfunction(func): """Wrap function that depend on hass.""" @wraps(func) def wrapper(*args, **kwargs): return func(hass, *args[1:], **kwargs) return contextfunction(wrapper) self.globals["expand"] = hassfunction(expand) self.filters["expand"] = contextfilter(self.globals["expand"]) self.globals["closest"] = hassfunction(closest) self.filters["closest"] = contextfilter(hassfunction(closest_filter)) self.globals["distance"] = hassfunction(distance) self.globals["is_state"] = hassfunction(is_state) self.globals["is_state_attr"] = hassfunction(is_state_attr) self.globals["state_attr"] = hassfunction(state_attr) self.globals["states"] = AllStates(hass)
def create_environment(site: Site, default_locale: Optional[str] = None) -> Environment: if default_locale is None: default_locale = site.configuration.default_locale url_generator = SiteUrlGenerator(site.configuration) template_directory_paths = list( [join(path, 'templates') for path in site.resources.paths]) environment = Environment( loader=FileSystemLoader(template_directory_paths), undefined=StrictUndefined, autoescape=select_autoescape(['html']), trim_blocks=True, lstrip_blocks=True, extensions=[ 'jinja2.ext.do', 'jinja2.ext.i18n', ], ) environment.install_gettext_translations(site.translations[default_locale]) environment.globals['site'] = site environment.globals['locale'] = default_locale environment.globals['plugins'] = _Plugins(site.plugins) environment.globals['EventType'] = Event.Type environment.globals['PresenceRole'] = Presence.Role environment.globals['urlparse'] = urlparse environment.filters['map'] = _filter_map environment.filters['flatten'] = _filter_flatten environment.filters['walk'] = _filter_walk environment.filters['takewhile'] = _filter_takewhile environment.filters['locale_get_data'] = lambda locale: Locale.parse( locale, '-') environment.filters[ 'negotiate_localizeds'] = lambda localizeds: negotiate_localizeds( default_locale, localizeds) environment.filters['sort_localizeds'] = contextfilter( lambda context, *args, **kwargs: _filter_sort_localizeds( context, default_locale, *args, **kwargs)) # A filter to convert any value to JSON. @contextfilter def _filter_json(context, data, indent=None): return stdjson.dumps(data, indent=indent, cls=JSONEncoder.get_factory( site.configuration, resolve_or_missing(context, 'locale'))) environment.filters['json'] = _filter_json # Override Jinja2's built-in JSON filter, which escapes the JSON for use in HTML, to use Betty's own encoder. @contextfilter def _filter_tojson(context, data, indent=None): return htmlsafe_json_dumps(data, indent=indent, dumper=lambda *args, **kwargs: _filter_json( context, *args, **kwargs)) environment.filters['tojson'] = _filter_tojson environment.tests['resource'] = lambda x: isinstance(x, Resource) environment.tests['identifiable'] = lambda x: isinstance(x, Identifiable) environment.filters['paragraphs'] = _filter_paragraphs def _filter_format_date(date: Datey): with Translations(site.translations[default_locale]): return format_datey(date, default_locale) environment.filters['format_date'] = _filter_format_date environment.filters['format_degrees'] = _filter_format_degrees environment.globals['citer'] = _Citer() def _filter_url(resource, content_type=None, locale=None, **kwargs): content_type = content_type if content_type else 'text/html' locale = locale if locale else default_locale return url_generator.generate(resource, content_type, locale=locale, **kwargs) environment.filters['url'] = _filter_url environment.filters['static_url'] = StaticPathUrlGenerator( site.configuration).generate environment.filters['file'] = lambda *args: _filter_file(site, *args) environment.filters['image'] = lambda *args, **kwargs: _filter_image( site, *args, **kwargs) environment.globals['search_index'] = lambda: index(site, environment) for plugin in site.plugins.values(): if isinstance(plugin, Jinja2Provider): environment.globals.update(plugin.globals) environment.filters.update(plugin.filters) return environment