@@ -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) | |||