The blog.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

63 lines
1.6 KiB

  1. from jinja2 import contextfilter, environmentfilter
  2. from jinja2.ext import Extension
  3. from io import StringIO
  4. from lxml import etree
  5. @contextfilter
  6. def rellinktoabs(context, value):
  7. env = context.environment
  8. # get the path for this context
  9. rel_path = context['resource'].relative_path
  10. content_url = env.globals['content_url'](context, rel_path)
  11. html = etree.HTML(value)
  12. # get all the fragment urls
  13. r = html.xpath("//a[@href[starts-with(.,'#')]]")
  14. for i in r:
  15. # prefix them w/ the content_url
  16. i.attrib['href'] = content_url + i.attrib['href']
  17. return etree.tostring(html, encoding='unicode', method='html')
  18. # mostly copied from hyde.ext.templates.jinja.py Markdown
  19. # and using docs from:
  20. # https://jinja.palletsprojects.com/en/2.10.x/extensions/#example-extension
  21. # to get the filter installed
  22. class RelLinktoAbs(Extension):
  23. """
  24. A wrapper around the rellinktoabs filter for syntactic sugar.
  25. """
  26. tags = { 'rellinktoabs' }
  27. def __init__(self, env):
  28. super(RelLinktoAbs, self).__init__(env)
  29. env.filters['rellinktoabs'] = rellinktoabs
  30. def parse(self, parser):
  31. """
  32. Parses the statements and defers to the callback
  33. for rellinktoabs processing.
  34. """
  35. lineno = next(parser.stream).lineno
  36. body = parser.parse_statements(['name:endrellinktoabs'], drop_needle=True)
  37. return nodes.CallBlock(
  38. self.call_method('_render_rellinktoabs'),
  39. [], [], body).set_lineno(lineno)
  40. def _render_rellinktoabs(self, caller=None):
  41. """
  42. Calls the rellinktoabs filter to transform the output.
  43. """
  44. if not caller:
  45. return ''
  46. output = caller().strip()
  47. return rellinktoabs(self.environment, output)