| Index: cms/converters.py | 
| =================================================================== | 
| --- a/cms/converters.py | 
| +++ b/cms/converters.py | 
| @@ -13,16 +13,17 @@ | 
| # You should have received a copy of the GNU General Public License | 
| # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 
| from __future__ import unicode_literals | 
|  | 
| import os | 
| import HTMLParser | 
| import re | 
| +import urlparse | 
|  | 
| import jinja2 | 
| import markdown | 
|  | 
|  | 
| # Monkey-patch Markdown's isBlockLevel function to ensure that no paragraphs | 
| # are inserted into the <head> tag | 
| orig_isBlockLevel = markdown.util.isBlockLevel | 
| @@ -391,16 +392,17 @@ | 
| 'toclist': self.toclist, | 
| } | 
|  | 
| globals = { | 
| 'get_string': self.get_string, | 
| 'has_string': self.has_string, | 
| 'get_page_content': self.get_page_content, | 
| 'get_pages_metadata': self.get_pages_metadata, | 
| +            'get_canonical_url': self.get_canonical_url, | 
| } | 
|  | 
| for dirname, dictionary in [('filters', filters), | 
| ('globals', globals)]: | 
| for filename in self._params['source'].list_files(dirname): | 
| root, ext = os.path.splitext(filename) | 
| if ext.lower() != '.py': | 
| continue | 
| @@ -512,16 +514,32 @@ | 
| filter_value = [filter_value] | 
| for option in filter_value: | 
| if str(option) not in metadata[filter_name]: | 
| return False | 
| elif filter_value != metadata[filter_name]: | 
| return False | 
| return True | 
|  | 
| +    def get_canonical_url(self, page): | 
| +        """Return canonical URL for the page (without locale code)""" | 
| +        try: | 
| +            base_url = self._params['site_url'] | 
| +        except KeyError: | 
| +            raise Exception('You must configure `siteurl` to use' | 
| +                            '`get_canonical_url()`') | 
| + | 
| +        locale, page_url = self._params['source'].resolve_link( | 
| +            page, self._params['locale'] | 
| +        ) | 
| +        # Remove the locale component that `resolve_link` adds at the | 
| +        # beginning. | 
| +        page_url = page_url[len(locale) + 1:] | 
| +        return urlparse.urljoin(base_url, page_url) | 
| + | 
| def toclist(self, content): | 
| toc_re = r'<h(\d)\s[^<>]*\bid="([^<>"]+)"[^<>]*>(.*?)</h\1>' | 
| flat = [] | 
| for match in re.finditer(toc_re, content, re.S): | 
| flat.append({ | 
| 'level': int(match.group(1)), | 
| 'anchor': jinja2.Markup(match.group(2)).unescape(), | 
| 'title': jinja2.Markup(match.group(3)).unescape(), | 
|  |