code: def apply(self):
          
          # In this phase, we replace the substitutions in hyperlinks
          # with the contents of the sub-nodes introduced during phase 1.
          # We also remove those temporary nodes from the tree.
          subst_re = re.compile(self.subst_pattern)
  
          # Apply the substitutions to hyperlink references.
          for link in self.document.traverse(nodes.reference):
              substitutions = link.get('varlinks')
              if not substitutions:
                  continue
  
              replacer = self._replace(substitutions, link.children, 1)
              link['refuri'] = subst_re.sub(replacer, link['refuri'])
              content = subst_re.sub(replacer, link[0])
              # Cleanup the temporary nodes and recreate the node's content.
              link.clear()
              del link['varlinks']
              link.append(nodes.Text(content))
  
          # Do the same with hyperlink targets.
          for link in self.document.traverse(nodes.target):
              substitutions = link.get('varlinks')
              if not substitutions:
                  continue
  
              replacer = self._replace(substitutions, link.children, 0)
              link['refuri'] = subst_re.sub(replacer, link['refuri'])
              # Cleanup the temporary nodes.
              link.clear()
              del link['varlinks']
docs: Replace substitutions in hyperlinks with their contents