A fork of hyde, the static site generation. Some patches will be pushed upstream.
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.
 
 
 

110 lines
3.3 KiB

  1. """
  2. Jinja template utilties
  3. """
  4. from hyde.fs import File, Folder
  5. from hyde.template import Template
  6. from jinja2 import contextfunction, Environment, FileSystemLoader, Undefined, nodes
  7. from jinja2.ext import Extension
  8. from jinja2.exceptions import TemplateError
  9. class SilentUndefined(Undefined):
  10. def __getattr__(self, name):
  11. return self
  12. __getitem__ = __getattr__
  13. def __call__(self, *args, **kwargs):
  14. return self
  15. @contextfunction
  16. def media_url(context, path):
  17. site = context['site']
  18. return Folder(site.config.media_url).child(path)
  19. @contextfunction
  20. def content_url(context, path):
  21. site = context['site']
  22. return Folder(site.config.base_url).child(path)
  23. class Markdown(Extension):
  24. tags = set(['markdown'])
  25. def parse(self, parser):
  26. lineno = parser.stream.next().lineno
  27. body = parser.parse_statements(['name:endmarkdown'], drop_needle=True)
  28. return nodes.CallBlock(
  29. self.call_method('_render_markdown', [], [], None, None),
  30. [], [], body
  31. ).set_lineno(lineno)
  32. def _render_markdown(self, caller=None):
  33. try:
  34. import markdown
  35. except ImportError:
  36. raise TemplateError("Cannot load the markdown library")
  37. if not caller:
  38. return ''
  39. output = caller().strip()
  40. d = {}
  41. if hasattr(self.environment.config, 'markdown'):
  42. d['extensions'] = getattr(self.environment.config.markdown, 'extensions', [])
  43. d['extension_configs'] = getattr(self.environment.config.markdown, 'extension_configs', {})
  44. md = markdown.Markdown(**d)
  45. return md.convert(output)
  46. # pylint: disable-msg=W0104,E0602,W0613,R0201
  47. class Jinja2Template(Template):
  48. """
  49. The Jinja2 Template implementation
  50. """
  51. def __init__(self, sitepath):
  52. super(Jinja2Template, self).__init__(sitepath)
  53. def configure(self, config):
  54. """
  55. Uses the config object to initialize the jinja environment.
  56. """
  57. if config:
  58. loader = FileSystemLoader([
  59. str(config.content_root_path),
  60. str(config.layout_root_path),
  61. ])
  62. else:
  63. loader = FileSystemLoader(str(self.sitepath))
  64. self.env = Environment(loader=loader,
  65. undefined=SilentUndefined,
  66. trim_blocks=True,
  67. extensions=[Markdown,
  68. 'jinja2.ext.do',
  69. 'jinja2.ext.loopcontrols',
  70. 'jinja2.ext.with_'])
  71. self.env.globals['media_url'] = media_url
  72. self.env.globals['content_url'] = content_url
  73. self.env.extend(config=config)
  74. try:
  75. from typogrify.templatetags import jinja2_filters
  76. except ImportError:
  77. jinja2_filters = False
  78. if jinja2_filters:
  79. jinja2_filters.register(self.env)
  80. @property
  81. def exception_class(self):
  82. return TemplateError
  83. def render(self, text, context):
  84. """
  85. Renders the given resource using the context
  86. """
  87. template = self.env.from_string(text)
  88. return template.render(context)