| @@ -13,3 +13,4 @@ build | |||
| *egg* | |||
| .idea | |||
| 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 | |||
| @@ -89,6 +89,8 @@ class MetaPlugin(Plugin): | |||
| 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) | |||
| @@ -48,7 +48,7 @@ class Generator(object): | |||
| res = function(*args) | |||
| if res: | |||
| targs = list(args) | |||
| last = targs.pop | |||
| last = targs.pop() | |||
| targs.append(res if res else last) | |||
| args = tuple(targs) | |||
| return res | |||
| @@ -35,13 +35,37 @@ class Template(object): | |||
| def exception_class(self): | |||
| 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): | |||
| """ | |||
| Returns a include statement for the current template, | |||
| Returns an include statement for the current template, | |||
| given the 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): | |||
| """ | |||
| Returns a open block statement for the current template, | |||
| @@ -56,6 +80,21 @@ class Template(object): | |||
| """ | |||
| 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 | |||
| 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): | |||
| TEST_SITE.delete() | |||
| def test_can_execute_less(self): | |||
| def test_can_parse_blockdown(self): | |||
| s = Site(TEST_SITE) | |||
| s.config.plugins = ['hyde.ext.plugins.blockdown.BlockdownPlugin'] | |||
| 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.generate_all() | |||
| 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]) | |||
| assert called_with_nodes == self.content_nodes | |||
| @@ -188,7 +187,6 @@ class TestPlugins(object): | |||
| gen = Generator(self.site) | |||
| gen.generate_all() | |||
| 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]) | |||
| assert called_with_nodes == self.content_nodes | |||
| @@ -207,7 +205,6 @@ class TestPlugins(object): | |||
| gen = Generator(self.site) | |||
| gen.generate_all() | |||
| 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 called_with_resources == self.content_text_resources | |||
| @@ -230,7 +227,6 @@ class TestPlugins(object): | |||
| gen = Generator(self.site) | |||
| gen.generate_all() | |||
| 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 called_with_resources == self.content_binary_resources | |||
| @@ -242,7 +238,6 @@ class TestPlugins(object): | |||
| path = self.site.content.source_folder.child('favicon.ico') | |||
| gen.generate_resource_at_path(path) | |||
| 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 called_with_resources[0] == path | |||