docs: def register(cls, library_register, nodename='cache', nocache_nodename='nocache'):
          """
          Register all needed templatetags, with these parameters :
              * library_register : the `register` object (result of
                  `template.Library()`) in your templatetag module
              * nodename : the node to use for the cache templatetag (the default
                  is "cache")
              * nocache_nodename : the node to use for the nocache templatetag
          """
  
          if cls in CacheTag._templatetags:
              raise RuntimeError('The adv-cache-tag class %s is already registered' % cls)
  
          CacheTag._templatetags[cls] = {}
  
          def templatetag_cache(parser, token):
              """
              Return a new Node object for the main cache templatetag
              """
              nodelist = parser.parse(('end%s' % nodename,))
              parser.delete_first_token()
              args = cls.get_template_node_arguments(token.contents.split())
              return cls.Node(nodename, nodelist, *args)
  
          library_register.tag(nodename, templatetag_cache)
          CacheTag._templatetags[cls]['cache'] = templatetag_cache
  
          def templatetag_raw(parser, token):
              """
              Return a TextNode with all html not parsed, used for templatetags
              that need to not be parsed : the `nocache` one and the `RAW` one,
              used to surround cached html (to be not parsed again)
              Based on http://www.holovaty.com/writing/django-two-phased-rendering/
              """
  
              # Whatever is between {% nocache %} and {% endnocache %} will be preserved as
              # raw, un-rendered template code.
  
              text = []
              parse_until = 'end%s' % token.contents
              tag_mapping = {
                  TOKEN_TEXT: ('', ''),
                  TOKEN_VAR: ('{{', '}}'),
                  TOKEN_BLOCK: ('{%', '%}'),
                  TOKEN_COMMENT: ('{#', '#}'),
              }
              # By the time this template tag is called, the template system has already
              # lexed the template into tokens. Here, we loop over the tokens until
              # {% endraw %} and parse them to TextNodes. We have to add the start and
              # end bits (e.g. "{{" for variables) because those have already been
              # stripped off in a previous part of the template-parsing process.
              while parser.tokens:
                  token = parser.next_token()
                  if token.token_type == TOKEN_BLOCK and token.contents == parse_until:
                      return template.TextNode(''.join(text))
                  start, end = tag_mapping[token.token_type]
                  text.append('%s%s%s' % (start, token.contents, end))
              parser.unclosed_block_tag(parse_until)
  
          library_register.tag(cls.RAW_TOKEN, templatetag_raw)
          CacheTag._templatetags[cls]['raw'] = templatetag_raw
  
          def templatetag_nocache(parser, token):
              """
              Return a TextNode with raw html from the `nocache` templatetag,
              and surround it with `endRAW` and `RAW` (precisely
              `cls.RAW_TOKEN_END` and `cls.RAW_TOKEN_START`).
              So for
                  {% nocache %}foo{% endnocache %}
              we get
                  {% endRAW... %}foo{% RAW... %}
              When the main cache templatetag content will be loaded from cache,
              it will be surrounded by the same templatetags, reversed.
              So if at first we had
                  {% cache %}bar{% nocache %}foo{% endnocache %}baz{% endcache %}
              The cached version will be
                  bar{% endRAW... %}foo{% RAW... %}baz
              And the final html to be rendered will be
                  {% RAW... %}bar{% endRAW... %}foo{% RAW... %}baz{% endRAW... %}
              And the html within `RAW` and `endRAW` will not be parsed, as wanted
              """
  
              # We'll load in the no-cache part all template tags and filters loaded in the main
              # template, to be able to use it when the no-cache will be rendered
  
              all_tags_and_filters = cls.get_all_tags_and_filters_by_function()
              available_tags = all_tags_and_filters['tags']
              available_filters = all_tags_and_filters['filters']
  
              needed = {}
              current_module = cls.get_templatetag_module()
  
              for function in parser.tags.values():
                  if function in available_tags:
                      lib, name = available_tags[function]
                      if lib == current_module:
                          continue
                      needed.setdefault(lib, set()).add(name)
  
              for function in parser.filters.values():
                  if function in available_filters:
                      lib, name = available_filters[function]
                      if lib == current_module:
                          continue
                      needed.setdefault(lib, set()).add(name)
  
              load_string = ''.join(
                  '%sload %s from %s%s' % (
                      template.BLOCK_TAG_START,
                      ' '.join(names),
                      lib,
                      template.BLOCK_TAG_END,
                  )
                  for lib, names in needed.items()
              )
  
              node = templatetag_raw(parser, token)
              node.s = cls.RAW_TOKEN_END + load_string + node.s + cls.RAW_TOKEN_START
              return node
  
          library_register.tag(nocache_nodename, templatetag_nocache)
          CacheTag._templatetags['nocache'] = templatetag_nocache