@@ -13,3 +13,4 @@ build | |||||
*egg* | *egg* | ||||
.idea | .idea | ||||
PYSMELLTAGS | PYSMELLTAGS | ||||
.noseids |
@@ -0,0 +1,39 @@ | |||||
""" | |||||
Autoextend css plugin | |||||
""" | |||||
from hyde.plugin import Plugin | |||||
import re | |||||
class AutoExtendPlugin(Plugin): | |||||
""" | |||||
The plugin class for less css | |||||
""" | |||||
def __init__(self, site): | |||||
super(AutoExtendPlugin, self).__init__(site) | |||||
def template_loaded(self, template): | |||||
self.template = template | |||||
def begin_text_resource(self, resource, text): | |||||
""" | |||||
If the meta data for the resource contains a layout attribute, | |||||
and there is no extends statement, this plugin automatically adds | |||||
an extends statement to the top of the file. | |||||
""" | |||||
layout = None | |||||
try: | |||||
layout = resource.meta.extends | |||||
except AttributeError: | |||||
pass | |||||
if layout: | |||||
extends_pattern = self.template.extends_pattern | |||||
if not re.search(extends_pattern, text): | |||||
extended_text = self.template.get_extends_statement(layout) | |||||
extended_text += '\n' | |||||
extended_text += text | |||||
text = extended_text | |||||
return text |
@@ -1,5 +1,5 @@ | |||||
""" | """ | ||||
Less css plugin | |||||
Blockdown css plugin | |||||
""" | """ | ||||
from hyde.plugin import Plugin | from hyde.plugin import Plugin | ||||
@@ -89,6 +89,8 @@ class MetaPlugin(Plugin): | |||||
text = text[match.end():] | text = text[match.end():] | ||||
data = match.group(1) | data = match.group(1) | ||||
if not hasattr(resource, 'meta') or not resource.meta: | 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) | resource.meta = Metadata(data, resource.node.meta) | ||||
else: | else: | ||||
resource.meta.update(data) | resource.meta.update(data) | ||||
@@ -48,7 +48,7 @@ class Generator(object): | |||||
res = function(*args) | res = function(*args) | ||||
if res: | if res: | ||||
targs = list(args) | targs = list(args) | ||||
last = targs.pop | |||||
last = targs.pop() | |||||
targs.append(res if res else last) | targs.append(res if res else last) | ||||
args = tuple(targs) | args = tuple(targs) | ||||
return res | return res | ||||
@@ -35,13 +35,37 @@ class Template(object): | |||||
def exception_class(self): | def exception_class(self): | ||||
return HydeException | return HydeException | ||||
@property | |||||
def include_pattern(self): | |||||
""" | |||||
The pattern for matching include statements | |||||
""" | |||||
return '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}' | |||||
def get_include_statement(self, path_to_include): | def get_include_statement(self, path_to_include): | ||||
""" | """ | ||||
Returns a include statement for the current template, | |||||
Returns an include statement for the current template, | |||||
given the path to include. | given the path to include. | ||||
""" | """ | ||||
return "{%% include '%s' %%}" % path_to_include | return "{%% include '%s' %%}" % path_to_include | ||||
@property | |||||
def block_open_pattern(self): | |||||
""" | |||||
The pattern for matching include statements | |||||
""" | |||||
return '\s*\{\%\s*block\s*([^\s]+)\s*\%\}' | |||||
@property | |||||
def block_close_pattern(self): | |||||
""" | |||||
The pattern for matching include statements | |||||
""" | |||||
return '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}' | |||||
def get_block_open_statement(self, block_name): | def get_block_open_statement(self, block_name): | ||||
""" | """ | ||||
Returns a open block statement for the current template, | Returns a open block statement for the current template, | ||||
@@ -56,6 +80,21 @@ class Template(object): | |||||
""" | """ | ||||
return "{%% endblock %s %%}" % block_name | return "{%% endblock %s %%}" % block_name | ||||
@property | |||||
def extends_pattern(self): | |||||
""" | |||||
The pattern for matching include statements | |||||
""" | |||||
return '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}' | |||||
def get_extends_statement(self, path_to_extend): | |||||
""" | |||||
Returns an extends statement for the current template, | |||||
given the path to extend. | |||||
""" | |||||
return "{%% extends '%s' %%}" % path_to_extend | |||||
@staticmethod | @staticmethod | ||||
def find_template(site): | def find_template(site): | ||||
""" | """ | ||||
@@ -0,0 +1,50 @@ | |||||
# -*- coding: utf-8 -*- | |||||
""" | |||||
Use nose | |||||
`$ pip install nose` | |||||
`$ nosetests` | |||||
""" | |||||
from hyde.fs import File, Folder | |||||
from hyde.generator import Generator | |||||
from hyde.site import Site | |||||
from pyquery import PyQuery | |||||
TEST_SITE = File(__file__).parent.parent.child_folder('_test') | |||||
class TestAutoExtend(object): | |||||
def setUp(self): | |||||
TEST_SITE.make() | |||||
TEST_SITE.parent.child_folder( | |||||
'sites/test_jinja').copy_contents_to(TEST_SITE) | |||||
def tearDown(self): | |||||
TEST_SITE.delete() | |||||
def test_can_auto_extend(self): | |||||
s = Site(TEST_SITE) | |||||
s.config.plugins = ['hyde.ext.plugins.meta.MetaPlugin', | |||||
'hyde.ext.plugins.auto_extend.AutoExtendPlugin', | |||||
'hyde.ext.plugins.blockdown.BlockdownPlugin'] | |||||
txt ="This template tests to make sure blocks can be replaced with markdownish syntax." | |||||
templ = """ | |||||
--- | |||||
extends: base.html | |||||
--- | |||||
===========================////title\\\\============================ | |||||
%s | |||||
===========================\\\\title////============================""" | |||||
content = (templ.strip() % txt).strip() | |||||
bd = File(TEST_SITE.child('content/auto_extend.html')) | |||||
bd.write(content) | |||||
gen = Generator(s) | |||||
gen.generate_resource_at_path(bd.path) | |||||
res = s.content.resource_from_path(bd.path) | |||||
target = File(s.config.deploy_root_path.child(res.relative_deploy_path)) | |||||
assert target.exists | |||||
text = target.read_all() | |||||
q = PyQuery(text) | |||||
assert q('title').text().strip() == txt.strip() |
@@ -23,7 +23,7 @@ class TestBlockdown(object): | |||||
def tearDown(self): | def tearDown(self): | ||||
TEST_SITE.delete() | TEST_SITE.delete() | ||||
def test_can_execute_less(self): | |||||
def test_can_parse_blockdown(self): | |||||
s = Site(TEST_SITE) | s = Site(TEST_SITE) | ||||
s.config.plugins = ['hyde.ext.plugins.blockdown.BlockdownPlugin'] | s.config.plugins = ['hyde.ext.plugins.blockdown.BlockdownPlugin'] | ||||
txt ="This template tests to make sure blocks can be replaced with markdownish syntax." | txt ="This template tests to make sure blocks can be replaced with markdownish syntax." | ||||
@@ -169,7 +169,6 @@ class TestPlugins(object): | |||||
gen = Generator(self.site) | gen = Generator(self.site) | ||||
gen.generate_all() | gen.generate_all() | ||||
assert begin_node_stub.call_count == len(self.content_nodes) | assert begin_node_stub.call_count == len(self.content_nodes) | ||||
called_with_nodes = sorted([arg[0][0].path for arg in begin_node_stub.call_args_list]) | called_with_nodes = sorted([arg[0][0].path for arg in begin_node_stub.call_args_list]) | ||||
assert called_with_nodes == self.content_nodes | assert called_with_nodes == self.content_nodes | ||||
@@ -188,7 +187,6 @@ class TestPlugins(object): | |||||
gen = Generator(self.site) | gen = Generator(self.site) | ||||
gen.generate_all() | gen.generate_all() | ||||
assert node_complete_stub.call_count == len(self.content_nodes) | assert node_complete_stub.call_count == len(self.content_nodes) | ||||
called_with_nodes = sorted([arg[0][0].path for arg in node_complete_stub.call_args_list]) | called_with_nodes = sorted([arg[0][0].path for arg in node_complete_stub.call_args_list]) | ||||
assert called_with_nodes == self.content_nodes | assert called_with_nodes == self.content_nodes | ||||
@@ -207,7 +205,6 @@ class TestPlugins(object): | |||||
gen = Generator(self.site) | gen = Generator(self.site) | ||||
gen.generate_all() | gen.generate_all() | ||||
called_with_resources = sorted([arg[0][0].path for arg in begin_text_resource_stub.call_args_list]) | called_with_resources = sorted([arg[0][0].path for arg in begin_text_resource_stub.call_args_list]) | ||||
assert begin_text_resource_stub.call_count == len(self.content_text_resources) | assert begin_text_resource_stub.call_count == len(self.content_text_resources) | ||||
assert called_with_resources == self.content_text_resources | assert called_with_resources == self.content_text_resources | ||||
@@ -230,7 +227,6 @@ class TestPlugins(object): | |||||
gen = Generator(self.site) | gen = Generator(self.site) | ||||
gen.generate_all() | gen.generate_all() | ||||
called_with_resources = sorted([arg[0][0].path for arg in begin_binary_resource_stub.call_args_list]) | called_with_resources = sorted([arg[0][0].path for arg in begin_binary_resource_stub.call_args_list]) | ||||
assert begin_binary_resource_stub.call_count == len(self.content_binary_resources) | assert begin_binary_resource_stub.call_count == len(self.content_binary_resources) | ||||
assert called_with_resources == self.content_binary_resources | assert called_with_resources == self.content_binary_resources | ||||
@@ -242,7 +238,6 @@ class TestPlugins(object): | |||||
path = self.site.content.source_folder.child('favicon.ico') | path = self.site.content.source_folder.child('favicon.ico') | ||||
gen.generate_resource_at_path(path) | gen.generate_resource_at_path(path) | ||||
called_with_resources = sorted([arg[0][0].path for arg in begin_binary_resource_stub.call_args_list]) | called_with_resources = sorted([arg[0][0].path for arg in begin_binary_resource_stub.call_args_list]) | ||||
assert begin_binary_resource_stub.call_count == 1 | assert begin_binary_resource_stub.call_count == 1 | ||||
assert called_with_resources[0] == path | assert called_with_resources[0] == path |