text: import re
  
  from django import VERSION as django_version
  from django import template
  from django.template.base import TemplateSyntaxError
  from django.template.defaultfilters import stringfilter
  from django.template.library import parse_bits
  from django.template.loader_tags import IncludeNode, construct_relative_path
  from django.utils.html import conditional_escape, mark_safe
  
  
  STARSPAN_RE = re.compile(r'(\*\*\*)(.+?)\1')
  
  register = template.Library()
  
  
  @register.simple_tag(name='set', takes_context=True)
  def set_tag(context, **kwargs):
      """
      The `set`` template tag add one or more context variables to the current
      template context. The context stack is respected.
  
      .. code-block:: text
  
          {% set foo="bar" baz=1 %}
          {{ foo }}
          {{ baz }}
  
      """
      # We cannot use context.update - this would break the context push/pop mech.
      for key, value in kwargs.items():
          context[key] = value
      return ''
  
  
  @register.filter
  @stringfilter
  def split(value, sep=' '):
      """
      The ``split`` template filter splits a given string by spaces. If you want
      to split by something else, provide the devider as a argument to the filter.
  
      .. code-block:: text
  
          {{ "foo bar"|split }}
          {{ "foo-bar"|split"-" }}
  
      """
      return value.split(sep)
  
  
  @register.filter
  @stringfilter
  def starspan(value):
      """
      The ``starspan`` template filter adds extra span element to star
      indicated text ("***text***").
  
      .. code-block:: text
  
          {{ some_text_variable|starspan }}
  
      """
      return mark_safe(STARSPAN_RE.sub(r'<span>\2</span>', conditional_escape(value)))
  
  
  @register.filter
  def merge_list(value, list_to_merge):
      """
      The ``merge_list`` filter combines two lists.
  
      .. code-block:: text
  
          {% for element in first_list|merge_list:second_list %}
              {{ element }}
          {% endfor %}
  
      To make the result list persistent use in combination with set tag.
  
      .. code-block:: text
  
          {% set new_list=first_list|merge_lists:second_list %}
  
      """
      if not type(value) == list or not type(list_to_merge) == list:
          raise TemplateSyntaxError(
              'Value and argument for merge_lists filter should be both of type '
              'list. Got "{0}" and "{1}".'.format(value, list_to_merge)
          )
  
      return value + list_to_merge
  
  
  class IncludeWithNode(IncludeNode):
      def __init__(self, with_object, template_name, *args, extra_context=None, **kwargs):
          self.with_object = template.Variable(with_object)
          super().__init__(
              template_name,
              *args,
              extra_context=extra_context,
              isolated_context=False,
              **kwargs,
          )
  
      def render(self, context):
          obj = None
          try:
              obj = self.with_object.resolve(context)
          except template.VariableDoesNotExist as exc:
              raise TemplateSyntaxError(
                  'Object {0} needs to be available in template context.'.format(
                      self.with_object.var
                  )
              ) from exc
          if not obj:
              raise TemplateSyntaxError(
                  'Object {0} is None. Provide corrct value.'.format(self.with_object.var)
              )
  
          exposed_attrs = getattr(obj, 'template_exposed_attributes', None)
          if exposed_attrs is None or not isinstance(exposed_attrs, (list, tuple)):
              raise TemplateSyntaxError(
                  'Object {0} should have template_exposed_attributes set'.format(
                      self.with_object.var
                  )
              )
  
          for exposed_attr in exposed_attrs:
              context[exposed_attr] = getattr(obj, exposed_attr)
          return super().render(context)
  
  
  @register.tag('include_with')
  def do_include_with(parser, token):
      """
      Include template with object attributes injected to context.
      It takes object and template path as arguments.
      Object should have template_exposed_attributes list defined.
  
      .. code-block:: text
  
          {% include_with obj 'path/to/included/template.html' %}
  
      It is also possible to overvrite / add additional kwaegs.
  
      .. code-block:: text
  
          {% include_with obj 'path/to/included/template.html' foo='bar'%}
  
      """
      bits = token.split_contents()
  
      if django_version[0] >= 2:
          options = parse_bits(
              parser,
              bits[1:],
              ['with_object', 'template_name'],
              False,
              True,
              None,
              [],
              None,
              False,
              'include_with',
          )
      else:
          options = parse_bits(
              parser,
              bits[1:],
              ['with_object', 'template_name'],
              False,
              True,
              None,
              False,
              'include_with',
          )
  
      bits[2] = construct_relative_path(parser.origin.template_name, bits[2])
      template_filter = parser.compile_filter(bits[2])
  
      return IncludeWithNode(bits[1], template_filter, extra_context=options[1])
  