Mercurial > wikked
changeset 53:c4e999f55ba9
Include changes:
- Better way to pre-parse include parameters.
- Added support for simple include templating.
- Added unit tests.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 31 Jan 2013 22:41:07 -0800 |
parents | 8167b9b6925a |
children | 9dfbc2a40b71 |
files | tests/test_page.py wikked/formatter.py |
diffstat | 2 files changed, 76 insertions(+), 20 deletions(-) [+] |
line wrap: on
line diff
--- a/tests/test_page.py Thu Jan 31 22:40:12 2013 -0800 +++ b/tests/test_page.py Thu Jan 31 22:41:07 2013 -0800 @@ -4,6 +4,11 @@ class PageTest(WikkedTest): + def _getWikiFromStructure(self, structure): + wiki = self.getWiki(use_db=False, fs_factory=lambda cfg: MockFileSystem(structure)) + wiki.start() + return wiki + def testSimplePage(self): self.wiki = self._getWikiFromStructure({ 'foo.txt': 'A test page.' @@ -58,11 +63,6 @@ self.assertEqual("Follow a link to the <a class=\"wiki-link\" data-wiki-url=\"sandbox\">Sandbox</a>. Or to <a class=\"wiki-link missing\" data-wiki-url=\"other-sandbox\">this page</a>.", page.formatted_text) self.assertEqual(set(['sandbox', 'other-sandbox']), set(page.local_links)) - def _getWikiFromStructure(self, structure): - wiki = self.getWiki(use_db=False, fs_factory=lambda cfg: MockFileSystem(structure)) - wiki.start() - return wiki - def testPageRelativeOutLinks(self): self.wiki = self._getWikiFromStructure({ 'first.txt': "Go to [[First Sibling]].", @@ -81,3 +81,37 @@ second2 = Page(self.wiki, 'sub_dir/second-sibling') self.assertEqual(['sub_dir/second'], second2.local_links) + def testPageInclude(self): + self.wiki = self._getWikiFromStructure({ + 'Foo.txt': "A test page.\n{{include: trans-desc}}\n", + 'Trans Desc.txt': "BLAH\n" + }) + foo = Page(self.wiki, 'foo') + self.assertEqual(['trans-desc'], foo.local_includes) + self.assertEqual("A test page.\n<div class=\"wiki-include\" data-wiki-url=\"trans-desc\"></div>\n", foo.formatted_text) + self.assertEqual("A test page.\nBLAH\n\n", foo.text) + + def testPageIncludeWithMeta(self): + self.wiki = self._getWikiFromStructure({ + 'Foo.txt': "A test page.\n{{include: trans-desc}}\n", + 'Trans Desc.txt': "BLAH: [[Somewhere]]\n{{bar: 42}}\n{{__secret: love}}\n{{+given: hope}}" + }) + foo = Page(self.wiki, 'foo') + self.assertEqual(['trans-desc'], foo.local_includes) + self.assertEqual([], foo.local_links) + self.assertEqual({'include': 'trans-desc'}, foo.local_meta) + self.assertEqual("A test page.\n<div class=\"wiki-include\" data-wiki-url=\"trans-desc\"></div>\n", foo.formatted_text) + self.assertEqual("A test page.\nBLAH: <a class=\"wiki-link missing\" data-wiki-url=\"somewhere\">Somewhere</a>\n\n\n\n", foo.text) + self.assertEqual(['trans-desc'], foo.all_includes) + self.assertEqual(['somewhere'], foo.all_links) + self.assertEqual({'bar': '42', 'given': 'hope', 'include': 'trans-desc'}, foo.all_meta) + + def testPageIncludeWithTemplating(self): + self.wiki = self._getWikiFromStructure({ + 'Foo.txt': "A test page.\n{{include: greeting|name=Dave|what=drink}}\n", + 'Greeting.txt': "Hello {{name}}, would you like a {{what}}?" + }) + foo = Page(self.wiki, 'foo') + self.assertEqual("A test page.\n<div class=\"wiki-include\" data-wiki-url=\"greeting\">name=Dave|what=drink</div>\n", foo.formatted_text) + self.assertEqual("A test page.\nHello Dave, would you like a drink?\n", foo.text) +
--- a/wikked/formatter.py Thu Jan 31 22:40:12 2013 -0800 +++ b/wikked/formatter.py Thu Jan 31 22:41:07 2013 -0800 @@ -111,10 +111,16 @@ return text def _processInclude(self, ctx, value): - included_url = ctx.getAbsoluteUrl(value) + pipe_idx = value.find('|') + if pipe_idx < 0: + included_url = ctx.getAbsoluteUrl(value) + parameters = '' + else: + included_url = ctx.getAbsoluteUrl(value[:pipe_idx]) + parameters = value[pipe_idx + 1:] ctx.included_pages.append(included_url) # Includes are run on the fly. - return '<div class="wiki-include">%s</div>\n' % included_url + return '<div class="wiki-include" data-wiki-url="%s">%s</div>\n' % (included_url, parameters) def _processQuery(self, ctx, query): # Queries are run on the fly. @@ -177,12 +183,12 @@ def run(self): def repl(m): - meta_name = str(m.group(1)) - meta_value = str(m.group(2)) + meta_name = str(m.group('name')) + meta_value = str(m.group('value')) if meta_name == 'query': return self._runQuery(meta_value) elif meta_name == 'include': - return self._runInclude(meta_value) + return self._runInclude(str(m.group('url')), meta_value) return '' self.ctx.url_trail = [self.page.url] @@ -191,17 +197,30 @@ self.ctx.meta = self.page.local_meta text = self.page.formatted_text - return re.sub(r'^<div class="wiki-([a-z]+)">(.*)</div>$', repl, text, + return re.sub(r'^<div class="wiki-(?P<name>[a-z]+)"( data-wiki-url="(?P<url>[^"]+)")?>(?P<value>.*)</div>$', repl, text, flags=re.MULTILINE) - def _runInclude(self, include_url): + def _runInclude(self, include_url, include_args): if include_url in self.ctx.url_trail: raise CircularIncludeError("Circular include detected at: %s" % include_url, self.ctx.url_trail) + + parameters = None + if include_args: + parameters = {} + arg_pattern = r"(^|\|)(?P<name>[a-zA-Z][a-zA-Z0-9_\-]+)=(?P<value>[^\|]+)" + for m in re.finditer(arg_pattern, include_args): + key = str(m.group('name')).lower() + parameters[key] = str(m.group('value')) + page = self.wiki.getPage(include_url) child_ctx = ResolvingContext() child = PageResolver(page, child_ctx) text = child.run() self.ctx.add(child_ctx) + + if parameters: + text = self._renderTemplate(text, parameters) + return text def _runQuery(self, query): @@ -210,12 +229,12 @@ meta_query = {} arg_pattern = r"(^|\|)(?P<name>[a-zA-Z][a-zA-Z0-9_\-]+)="\ r"(?P<value>[^\|]+)" - for m in re.findall(arg_pattern, query): - key = m[1].lower() + for m in re.finditer(arg_pattern, query): + key = m.group('name').lower() if key not in parameters: - meta_query[key] = m[2] + meta_query[key] = m.group('value') else: - parameters[key] = m[2] + parameters[key] = m.group('value') # Find pages that match the query, excluding any page # that is in the URL trail. @@ -234,14 +253,11 @@ # Combine normal templates to build the output. text = parameters['header'] for p in matched_pages: - item_str = parameters['item'] tokens = { 'url': p.url, 'title': p.title } - for tk, tv in tokens.iteritems(): - item_str = item_str.replace('{{%s}}' % tk, tv) - text += item_str + text += self._renderTemplate(parameters['item'], tokens) text += parameters['footer'] return text @@ -266,3 +282,9 @@ p = self.wiki.getPage(url) if self._isPageMatch(p, name, value, level + 1): return True + + def _renderTemplate(self, text, parameters): + for token, value in parameters.iteritems(): + text = text.replace('{{%s}}' % token, value) + return text +