Mercurial > wikked
changeset 106:212dfbb75031
Page formatter/resolver changeS:
* Better handle edge cases in inclusions, do more stuff at the end
of the resolving step.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 12 Nov 2013 13:50:26 -0800 |
parents | 986f399a1471 |
children | 2654e243de8c |
files | wikked/formatter.py wikked/resolver.py wikked/utils.py |
diffstat | 3 files changed, 62 insertions(+), 42 deletions(-) [+] |
line wrap: on
line diff
--- a/wikked/formatter.py Tue Nov 12 13:48:06 2013 -0800 +++ b/wikked/formatter.py Tue Nov 12 13:50:26 2013 -0800 @@ -1,7 +1,7 @@ import os import os.path import re -from utils import get_absolute_url, get_meta_name_and_modifiers +from utils import get_meta_name_and_modifiers class BaseContext(object): @@ -13,9 +13,6 @@ def urldir(self): return os.path.dirname(self.url) - def getAbsoluteUrl(self, url, do_slugify=True): - return get_absolute_url(self.url, url, do_slugify) - class FormattingContext(BaseContext): """ Context for formatting pages. """ @@ -122,9 +119,9 @@ def _coerceInclude(self, ctx, value): pipe_idx = value.find('|') if pipe_idx < 0: - return ctx.getAbsoluteUrl(value.strip()) + return value.strip() else: - url = ctx.getAbsoluteUrl(value[:pipe_idx].strip()) + url = value[:pipe_idx].strip() parameters = value[pipe_idx + 1:].replace('\n', '') return url + '|' + parameters @@ -154,12 +151,6 @@ for m in re.finditer(arg_pattern, query): name = str(m.group('name')).strip() value = str(m.group('value')).strip() - if re.match(r'^\[\[.*\]\]$', value): - url = value[2:-2] - abs_url = ctx.getAbsoluteUrl(url) - value = '[[%s]]' % abs_url - if len(processed_args) > 0: - processed_args += '|' processed_args += '%s=%s' % (name, value) mod_attr = '' @@ -168,9 +159,8 @@ return '<div class="wiki-query"%s>%s</div>\n' % (mod_attr, processed_args) def _formatWikiLink(self, ctx, display, url): - abs_url = ctx.getAbsoluteUrl(url) - ctx.out_links.append(abs_url) - return '<a class="wiki-link" data-wiki-url="%s">%s</a>' % (abs_url, display) + ctx.out_links.append(url) + return '<a class="wiki-link" data-wiki-url="%s">%s</a>' % (url, display) @staticmethod def parseWikiLinks(text):
--- a/wikked/resolver.py Tue Nov 12 13:48:06 2013 -0800 +++ b/wikked/resolver.py Tue Nov 12 13:50:26 2013 -0800 @@ -1,6 +1,8 @@ import re +import os.path import jinja2 -from utils import get_meta_name_and_modifiers +from utils import (get_meta_name_and_modifiers, namespace_title_to_url, + get_absolute_url) class FormatterNotFound(Exception): @@ -36,6 +38,11 @@ return len(self.url_trail) > 1 raise ValueError("Unknown modifier: " + modifier) + def getAbsoluteUrl(self, url, base_url=None): + if base_url is None: + base_url = self.root_page.url + return get_absolute_url(base_url, url) + class ResolveOutput(object): """ The results of a resolve operation. """ @@ -81,6 +88,11 @@ self.output = None self.env = None + self.resolvers = { + 'query': self._runQuery, + 'include': self._runInclude + } + @property def wiki(self): return self.page.wiki @@ -93,6 +105,8 @@ try: return self._unsafeRun() except Exception as e: + self.wiki.logger.error("Error resolving page '%s':" % self.page.url) + self.wiki.logger.exception(e) self.output = ResolveOutput(self.page) self.output.text = u'<div class="error">%s</div>' % e return self.output @@ -100,10 +114,13 @@ def _unsafeRun(self): # Create default parameters. if not self.parameters: + urldir = os.path.dirname(self.page.url) + full_title = os.path.join(urldir, self.page.title).replace('\\', '/') self.parameters = { '__page': { 'url': self.page.url, - 'title': self.page.title + 'title': self.page.title, + 'full_title': full_title }, '__args': [] } @@ -112,17 +129,8 @@ # with child outputs (from included pages). self.output = ResolveOutput(self.page) - # Resolve link states. - def repl1(m): - url = str(m.group('url')) - if self.wiki.pageExists(url): - return str(m.group()) - return '<a class="wiki-link missing" data-wiki-url="%s">' % url - - final_text = re.sub( - r'<a class="wiki-link" data-wiki-url="(?P<url>[^"]+)">', - repl1, - self.page.getFormattedText()) + # Start with the page's text. + final_text = self.page.getFormattedText() # Resolve queries, includes, etc. def repl2(m): @@ -137,10 +145,9 @@ opt_value = str(c.group('value')) meta_opts[opt_name] = opt_value - if meta_name == 'query': - return self._runQuery(meta_opts, meta_value) - elif meta_name == 'include': - return self._runInclude(meta_opts, meta_value) + resolver = self.resolvers.get(meta_name) + if resolver: + return resolver(meta_opts, meta_value) return '' final_text = re.sub( @@ -151,11 +158,29 @@ final_text, flags=re.MULTILINE) - # Run text through templating and formatting if this - # is the root page. + # If this is the root page, with all the includes resolved and + # collapsed into one text, we need to run the final steps. if self.is_root: + # Resolve any `{{foo}}` variable references. parameters = dict(self.parameters) final_text = self._renderTemplate(final_text, parameters, error_url=self.page.url) + + # Resolve link states. + def repl1(m): + raw_url = str(m.group('url')) + raw_url = self.ctx.getAbsoluteUrl(raw_url) + url = namespace_title_to_url(raw_url) + self.wiki.logger.debug("Converting '%s' to '%s'" % (raw_url, url)) + if self.wiki.pageExists(url): + return '<a class="wiki-link" data-wiki-url="%s">' % url + return '<a class="wiki-link missing" data-wiki-url="%s">' % url + + final_text = re.sub( + r'<a class="wiki-link" data-wiki-url="(?P<url>[^"]+)">', + repl1, + final_text) + + # Format the text. formatter = self._getFormatter(self.page.extension) final_text = formatter(final_text) @@ -170,7 +195,7 @@ return '' # Check for circular includes. - include_url = opts['url'] + include_url = self.ctx.getAbsoluteUrl(opts['url'], self.page.url) if include_url in self.ctx.url_trail: raise CircularIncludeError("Circular include detected at: %s" % include_url, self.ctx.url_trail)
--- a/wikked/utils.py Tue Nov 12 13:48:06 2013 -0800 +++ b/wikked/utils.py Tue Nov 12 13:50:26 2013 -0800 @@ -15,15 +15,20 @@ raw_abs_url = os.path.join(urldir, url) abs_url = os.path.normpath(raw_abs_url).replace('\\', '/') if do_slugify: - abs_url_parts = abs_url.split('/') - abs_url = '' - for i, part in enumerate(abs_url_parts): - if i > 0: - abs_url += '/' - abs_url += title_to_url(part) + abs_url = namespace_title_to_url(abs_url) return abs_url +def namespace_title_to_url(url): + url_parts = url.split('/') + result = '' + for i, part in enumerate(url_parts): + if i > 0: + result += '/' + result += title_to_url(part) + return result + + def title_to_url(title): # Remove diacritics (accents, etc.) and replace them with ASCII # equivelent. @@ -31,7 +36,7 @@ unicodedata.normalize('NFD', unicode(title)) if unicodedata.category(c) != 'Mn')) # Now replace spaces and punctuation with a hyphen. - return re.sub(r'[^A-Za-z0-9_\.\-\(\)]+', '-', ansi_title.lower()) + return re.sub(r'[^A-Za-z0-9_\.\-\(\)\{\}]+', '-', ansi_title.lower()) def url_to_title(url):