| @@ -0,0 +1,40 @@ | |||||
| # -*- coding: utf-8 -*- | |||||
| """ | |||||
| Textlinks plugin | |||||
| """ | |||||
| import re | |||||
| from hyde.plugin import Plugin | |||||
| class TextlinksPlugin(Plugin): | |||||
| """ | |||||
| The plugin class for syntax text replacement. | |||||
| """ | |||||
| def __init__(self, site): | |||||
| super(TextlinksPlugin, self).__init__(site) | |||||
| def template_loaded(self, template): | |||||
| """ | |||||
| Handles the template loaded event to keep | |||||
| a reference to the template object. | |||||
| """ | |||||
| self.template = template | |||||
| def begin_text_resource(self, resource, text): | |||||
| """ | |||||
| Replace content url pattern [[/abc/def]]) | |||||
| with | |||||
| {{ content_url('/abc/def') }} or equivalent and | |||||
| Replace media url pattern [[!!/abc/def]] | |||||
| with | |||||
| {{ media_url('/abc/def') }} or equivalent. | |||||
| """ | |||||
| content_link = re.compile('\[\[([^\]]*)\]\]', re.UNICODE|re.MULTILINE) | |||||
| media_link = re.compile('\[\[\!\!([^\]]*)\]\]', re.UNICODE|re.MULTILINE) | |||||
| def replace_content(match): | |||||
| return self.template.get_content_url_statement(match.groups(1)[0]) | |||||
| def replace_media(match): | |||||
| return self.template.get_media_url_statement(match.groups(1)[0]) | |||||
| text = content_link.sub(replace_content, text) | |||||
| text = media_link.sub(replace_media, text) | |||||
| return text | |||||
| @@ -383,42 +383,53 @@ class Jinja2Template(Template): | |||||
| @property | @property | ||||
| def patterns(self): | def patterns(self): | ||||
| """ | |||||
| The pattern for matching selected template statements. | |||||
| """ | |||||
| return { | |||||
| """ | |||||
| The pattern for matching selected template statements. | |||||
| """ | |||||
| return { | |||||
| "block_open": '\s*\{\%\s*block\s*([^\s]+)\s*\%\}', | "block_open": '\s*\{\%\s*block\s*([^\s]+)\s*\%\}', | ||||
| "block_close": '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}', | "block_close": '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}', | ||||
| "include": '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}', | "include": '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}', | ||||
| "extends": '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}' | "extends": '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}' | ||||
| } | |||||
| } | |||||
| def get_include_statement(self, path_to_include): | def get_include_statement(self, path_to_include): | ||||
| """ | |||||
| Returns an include statement for the current template, | |||||
| given the path to include. | |||||
| """ | |||||
| return '{%% include \'%s\' %%}' % path_to_include | |||||
| """ | |||||
| Returns an include statement for the current template, | |||||
| given the path to include. | |||||
| """ | |||||
| return '{%% include \'%s\' %%}' % path_to_include | |||||
| def get_extends_statement(self, path_to_extend): | 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 | |||||
| """ | |||||
| Returns an extends statement for the current template, | |||||
| given the path to extend. | |||||
| """ | |||||
| return '{%% extends \'%s\' %%}' % path_to_extend | |||||
| def get_open_tag(self, tag, params): | def get_open_tag(self, tag, params): | ||||
| """ | |||||
| Returns an open tag statement. | |||||
| """ | |||||
| return '{%% %s %s -%%}' % (tag, params) | |||||
| """ | |||||
| Returns an open tag statement. | |||||
| """ | |||||
| return '{%% %s %s -%%}' % (tag, params) | |||||
| def get_close_tag(self, tag, params): | def get_close_tag(self, tag, params): | ||||
| """ | |||||
| Returns an open tag statement. | |||||
| """ | |||||
| return '{%%- end%s %%}' % tag | |||||
| """ | |||||
| Returns an open tag statement. | |||||
| """ | |||||
| return '{%%- end%s %%}' % tag | |||||
| def get_content_url_statement(self, url): | |||||
| """ | |||||
| Returns the content url statement. | |||||
| """ | |||||
| return '{{ content_url(\'%s\') }}' % url | |||||
| def get_media_url_statement(self, url): | |||||
| """ | |||||
| Returns the media url statement. | |||||
| """ | |||||
| return '{{ media_url(\'%s\') }}' % url | |||||
| def render(self, text, context): | def render(self, text, context): | ||||
| """ | """ | ||||
| @@ -128,6 +128,20 @@ class Template(object): | |||||
| """ | """ | ||||
| return '{%% end%s %%}' % tag | return '{%% end%s %%}' % tag | ||||
| @abc.abstractmethod | |||||
| def get_content_url_statement(self, url): | |||||
| """ | |||||
| Returns the content url statement. | |||||
| """ | |||||
| return '/' + url | |||||
| @abc.abstractmethod | |||||
| def get_media_url_statement(self, url): | |||||
| """ | |||||
| Returns the media url statement. | |||||
| """ | |||||
| return '/media/' + url | |||||
| @staticmethod | @staticmethod | ||||
| def find_template(site): | def find_template(site): | ||||
| """ | """ | ||||
| @@ -136,6 +136,55 @@ class TestSorter(object): | |||||
| File(p).parent.name]))] | File(p).parent.name]))] | ||||
| assert pages == expected_sorted | assert pages == expected_sorted | ||||
| # def test_walk_resources_sorted_with_grouping_one_level(self): | |||||
| # s = Site(TEST_SITE) | |||||
| # cfg = """ | |||||
| # plugins: | |||||
| # - hyde.ext.sorter.SorterPlugin | |||||
| # sorter: | |||||
| # multi: | |||||
| # groups: sections.yaml | |||||
| # attr: | |||||
| # - source_file.kind | |||||
| # - node.name | |||||
| # | |||||
| # """ | |||||
| # sections = """ | |||||
| # group_name: section | |||||
| # groups: | |||||
| # - | |||||
| # name: support | |||||
| # description: All site support pages | |||||
| # - | |||||
| # name: media | |||||
| # description: Media files | |||||
| # """ | |||||
| # s.config = Config(TEST_SITE, config_dict=yaml.load(cfg)) | |||||
| # s.load() | |||||
| # SorterPlugin(s).begin_site() | |||||
| # | |||||
| # assert hasattr(s.content, 'walk_resources_sorted_by_multi') | |||||
| # expected = ["content/404.html", | |||||
| # "content/about.html", | |||||
| # "content/apple-touch-icon.png", | |||||
| # "content/blog/2010/december/merry-christmas.html", | |||||
| # "content/crossdomain.xml", | |||||
| # "content/favicon.ico", | |||||
| # "content/robots.txt", | |||||
| # "content/site.css" | |||||
| # ] | |||||
| # | |||||
| # pages = [page.name for page in s.content.walk_resources_sorted_by_multi()] | |||||
| # | |||||
| # expected_sorted = [File(page).name | |||||
| # for page in | |||||
| # sorted(expected, | |||||
| # key=lambda p: tuple( | |||||
| # [File(p).kind, | |||||
| # File(p).parent.name]))] | |||||
| # assert pages == expected_sorted | |||||
| def test_walk_resources_sorted_no_default_is_processable(self): | def test_walk_resources_sorted_no_default_is_processable(self): | ||||
| s = Site(TEST_SITE) | s = Site(TEST_SITE) | ||||
| cfg = """ | cfg = """ | ||||
| @@ -25,7 +25,7 @@ class TestSyntext(object): | |||||
| def test_mark(self): | |||||
| def test_syntext(self): | |||||
| text = u""" | text = u""" | ||||
| ~~~~~~~~css~~~~~~~ | ~~~~~~~~css~~~~~~~ | ||||
| .body{ | .body{ | ||||
| @@ -0,0 +1,57 @@ | |||||
| # -*- 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 TestTextlinks(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_textlinks(self): | |||||
| d = { | |||||
| 'objects': 'template/variables', | |||||
| 'plugins': 'plugins/metadata', | |||||
| 'sorter': 'plugins/sorter' | |||||
| } | |||||
| text = u""" | |||||
| {%% markdown %%} | |||||
| * [Rich object model][hyde objects] and | |||||
| [overridable hierarchical metadata]([[%(plugins)s]]) thats available for use in | |||||
| templates. | |||||
| * Configurable [sorting][], filtering and grouping support. | |||||
| [hyde objects]: [[%(objects)s]] | |||||
| [sorting]: [[%(sorter)s]] | |||||
| {%% endmarkdown %%} | |||||
| """ | |||||
| site = Site(TEST_SITE) | |||||
| site.config.plugins = ['hyde.ext.plugins.textlinks.TextlinksPlugin'] | |||||
| site.config.base_url = 'http://example.com/' | |||||
| tlink = File(site.content.source_folder.child('tlink.html')) | |||||
| tlink.write(text % d) | |||||
| gen = Generator(site) | |||||
| gen.generate_all() | |||||
| f = File(site.config.deploy_root_path.child(tlink.name)) | |||||
| assert f.exists | |||||
| html = f.read_all() | |||||
| assert html | |||||
| for name, path in d.items(): | |||||
| assert site.config.base_url + path in html | |||||