| @@ -84,19 +84,34 @@ class MetaPlugin(Plugin): | |||
| match = re.match(yaml_finder, text) | |||
| if not match: | |||
| logger.info("No metadata found in resource [%s]" % resource) | |||
| return text | |||
| text = text[match.end():] | |||
| data = match.group(1) | |||
| data = {} | |||
| else: | |||
| text = text[match.end():] | |||
| data = match.group(1) | |||
| if not hasattr(resource, 'meta') or not resource.meta: | |||
| if not hasattr(resource.node, 'meta'): | |||
| resource.node.meta = Metadata({}) | |||
| resource.meta = Metadata(data, resource.node.meta) | |||
| else: | |||
| resource.meta.update(data) | |||
| self.__update_standard_attributes__(resource) | |||
| logger.info("Successfully loaded metadata from resource [%s]" | |||
| % resource) | |||
| return text | |||
| def __update_standard_attributes__(self, obj): | |||
| """ | |||
| Updates standard attributes on the resource and | |||
| page based on the provided meta data. | |||
| """ | |||
| if not hasattr(obj, 'meta'): | |||
| return | |||
| standard_attributes = ['is_processable', 'uses_template'] | |||
| for attr in standard_attributes: | |||
| if hasattr(obj.meta, attr): | |||
| setattr(obj, attr, getattr(obj.meta, attr)) | |||
| def __read_node__(self, node): | |||
| """ | |||
| Look for nodemeta.yaml. Load and assign it to the node. | |||
| @@ -112,6 +127,7 @@ class MetaPlugin(Plugin): | |||
| node.meta = Metadata(metadata, parent=parent_meta) | |||
| else: | |||
| node.meta = Metadata({}, parent=parent_meta) | |||
| self.__update_standard_attributes__(node) | |||
| def begin_node(self, node): | |||
| """ | |||
| @@ -4,7 +4,8 @@ Jinja template utilties | |||
| from hyde.fs import File, Folder | |||
| from hyde.template import Template | |||
| from jinja2 import contextfunction, Environment, FileSystemLoader, Undefined, nodes | |||
| from jinja2 import contextfunction, Environment, FileSystemLoader | |||
| from jinja2 import environmentfilter, Markup, Undefined, nodes | |||
| from jinja2.ext import Extension | |||
| from jinja2.exceptions import TemplateError | |||
| @@ -30,6 +31,20 @@ def content_url(context, path): | |||
| site = context['site'] | |||
| return Folder(site.config.base_url).child(path) | |||
| @environmentfilter | |||
| def markdown(env, value): | |||
| try: | |||
| import markdown | |||
| except ImportError: | |||
| raise TemplateError("Cannot load the markdown library") | |||
| output = value | |||
| d = {} | |||
| if hasattr(env.config, 'markdown'): | |||
| d['extensions'] = getattr(env.config.markdown, 'extensions', []) | |||
| d['extension_configs'] = getattr(env.config.markdown, 'extension_configs', {}) | |||
| md = markdown.Markdown(**d) | |||
| return md.convert(output) | |||
| class Markdown(Extension): | |||
| tags = set(['markdown']) | |||
| @@ -43,19 +58,10 @@ class Markdown(Extension): | |||
| ).set_lineno(lineno) | |||
| def _render_markdown(self, caller=None): | |||
| try: | |||
| import markdown | |||
| except ImportError: | |||
| raise TemplateError("Cannot load the markdown library") | |||
| if not caller: | |||
| return '' | |||
| output = caller().strip() | |||
| d = {} | |||
| if hasattr(self.environment.config, 'markdown'): | |||
| d['extensions'] = getattr(self.environment.config.markdown, 'extensions', []) | |||
| d['extension_configs'] = getattr(self.environment.config.markdown, 'extension_configs', {}) | |||
| md = markdown.Markdown(**d) | |||
| return md.convert(output) | |||
| return markdown(self.environment, output) | |||
| # pylint: disable-msg=W0104,E0602,W0613,R0201 | |||
| class Jinja2Template(Template): | |||
| @@ -80,13 +86,14 @@ class Jinja2Template(Template): | |||
| self.env = Environment(loader=loader, | |||
| undefined=SilentUndefined, | |||
| trim_blocks=True, | |||
| extensions=[Markdown, | |||
| 'jinja2.ext.do', | |||
| extensions=[Markdown, | |||
| 'jinja2.ext.do', | |||
| 'jinja2.ext.loopcontrols', | |||
| 'jinja2.ext.with_']) | |||
| self.env.globals['media_url'] = media_url | |||
| self.env.globals['content_url'] = content_url | |||
| self.env.extend(config=config) | |||
| self.env.filters['markdown'] = markdown | |||
| try: | |||
| from typogrify.templatetags import jinja2_filters | |||
| @@ -212,8 +212,9 @@ class Generator(object): | |||
| if resource.source_file.is_text: | |||
| text = resource.source_file.read_all() | |||
| text = self.events.begin_text_resource(resource, text) or text | |||
| logger.info("Rendering [%s]", resource) | |||
| text = self.template.render(text, context) | |||
| if resource.uses_template: | |||
| logger.info("Rendering [%s]", resource) | |||
| text = self.template.render(text, context) | |||
| text = self.events.text_resource_complete( | |||
| resource, text) or text | |||
| target = File(self.site.config.deploy_root_path.child( | |||
| @@ -120,10 +120,7 @@ class HydeWebServer(HTTPServer): | |||
| self.exception_count += 1 | |||
| logger.error('Error occured when regenerating the site [%s]' | |||
| % exception.message) | |||
| if self.exception_count > 1: | |||
| self.shutdown() | |||
| exit() | |||
| else: | |||
| if self.exception_count <= 1: | |||
| self.__reinit__() | |||
| @@ -22,6 +22,7 @@ class Processable(object): | |||
| super(Processable, self).__init__() | |||
| self.source = FS.file_or_folder(source) | |||
| self.is_processable = True | |||
| self.uses_template = True | |||
| @property | |||
| def name(self): | |||
| @@ -26,6 +26,26 @@ class TestMeta(object): | |||
| def tearDown(self): | |||
| TEST_SITE.delete() | |||
| def test_can_set_standard_attributes(self): | |||
| text = """ | |||
| --- | |||
| is_processable: False | |||
| --- | |||
| {% extends "base.html" %} | |||
| """ | |||
| about2 = File(TEST_SITE.child('content/about2.html')) | |||
| about2.write(text) | |||
| s = Site(TEST_SITE) | |||
| s.load() | |||
| res = s.content.resource_from_path(about2.path) | |||
| assert res.is_processable | |||
| s.config.plugins = ['hyde.ext.plugins.meta.MetaPlugin'] | |||
| gen = Generator(s) | |||
| gen.generate_all() | |||
| assert not res.meta.is_processable | |||
| assert not res.is_processable | |||
| def test_can_load_front_matter(self): | |||
| d = {'title': 'A nice title', | |||
| 'author': 'Lakshmi Vyas', | |||
| @@ -47,6 +47,20 @@ def test_generate_resource_from_path_with_is_processable_false(): | |||
| about = File(Folder(site.config.deploy_root_path).child('about.html')) | |||
| assert not about.exists | |||
| @with_setup(create_test_site, delete_test_site) | |||
| def test_generate_resource_from_path_with_uses_template_false(): | |||
| site = Site(TEST_SITE) | |||
| site.load() | |||
| resource = site.content.resource_from_path(TEST_SITE.child('content/about.html')) | |||
| resource.uses_template = False | |||
| gen = Generator(site) | |||
| gen.generate_resource_at_path(TEST_SITE.child('content/about.html')) | |||
| about = File(Folder(site.config.deploy_root_path).child('about.html')) | |||
| assert about.exists | |||
| text = about.read_all() | |||
| expected = resource.source_file.read_all() | |||
| assert text == expected | |||
| @with_setup(create_test_site, delete_test_site) | |||
| def test_generate_resource_from_path_with_deploy_override(): | |||
| site = Site(TEST_SITE) | |||