- BREAKING: While this change will correct the weird encoding
behavior, this also changes the way `xxx_url` macros work.
- Do not encode the url bases (`base_url`, `media_url`). Only
the path component needs to be encoded.
main
| @@ -1,11 +1,21 @@ | |||||
| Version 0.8.7a9 | |||||
| ============================================================ | |||||
| * Ensure external urls are encoded properly. (Issue #158). | |||||
| - BREAKING: While this change will correct the weird encoding | |||||
| behavior, this also changes the way `xxx_url` macros work. | |||||
| - Do not encode the url bases (`base_url`, `media_url`). Only | |||||
| the path component needs to be encoded. | |||||
| Version 0.8.7a8 | Version 0.8.7a8 | ||||
| ============================================================ | ============================================================ | ||||
| * Fix subfolders for root paths on windows. (Issue #167). | * Fix subfolders for root paths on windows. (Issue #167). | ||||
| - Using subfolders for `layout_root`, `content_root`, | |||||
| `media_root` and `deploy_root` now works reliably | |||||
| on windows. | |||||
| - Ensure that subfolders for `layout_root`, `content_root`, | |||||
| `media_root` and `deploy_root` works reliably | |||||
| on windows. Use `fully_expanded_path` for all path components. | |||||
| Version 0.8.7a7 | Version 0.8.7a7 | ||||
| @@ -1,4 +1,4 @@ | |||||
| Version 0.8.7a8 | |||||
| Version 0.8.7a9 | |||||
| A brand new **hyde** | A brand new **hyde** | ||||
| ==================== | ==================== | ||||
| @@ -383,6 +383,13 @@ class RootNode(Node): | |||||
| if dont_ignore(afile.name): | if dont_ignore(afile.name): | ||||
| self.add_resource(afile) | self.add_resource(afile) | ||||
| def _encode_path(base, path, safe): | |||||
| base = base.strip().replace(os.sep, '/').encode('utf-8') | |||||
| path = path.strip().replace(os.sep, '/').encode('utf-8') | |||||
| path = quote(path, safe) if safe is not None else quote(path) | |||||
| return base.rstrip('/') + '/' + path.lstrip('/') | |||||
| class Site(object): | class Site(object): | ||||
| """ | """ | ||||
| Represents the site to be generated. | Represents the site to be generated. | ||||
| @@ -425,35 +432,28 @@ class Site(object): | |||||
| """ | """ | ||||
| self.content.load() | self.content.load() | ||||
| def _safe_chars(self, safe=None): | |||||
| if safe is not None: | |||||
| return safe | |||||
| elif self.config.encode_safe is not None: | |||||
| return self.config.encode_safe | |||||
| else: | |||||
| return None | |||||
| def content_url(self, path, safe=None): | def content_url(self, path, safe=None): | ||||
| """ | """ | ||||
| Returns the content url by appending the base url from the config | Returns the content url by appending the base url from the config | ||||
| with the given path. The return value is url encoded. | with the given path. The return value is url encoded. | ||||
| """ | """ | ||||
| fpath = Folder(self.config.base_url) \ | |||||
| .child(path) \ | |||||
| .replace(os.sep, '/').encode("utf-8") | |||||
| if safe is not None: | |||||
| return quote(fpath, safe) | |||||
| elif self.config.encode_safe is not None: | |||||
| return quote(fpath, self.config.encode_safe) | |||||
| else: | |||||
| return quote(fpath) | |||||
| return _encode_path(self.config.base_url, path, self._safe_chars(safe)) | |||||
| def media_url(self, path, safe=None): | def media_url(self, path, safe=None): | ||||
| """ | """ | ||||
| Returns the media url by appending the media base url from the config | Returns the media url by appending the media base url from the config | ||||
| with the given path. The return value is url encoded. | with the given path. The return value is url encoded. | ||||
| """ | """ | ||||
| fpath = Folder(self.config.media_url) \ | |||||
| .child(path) \ | |||||
| .replace(os.sep, '/').encode("utf-8") | |||||
| if safe is not None: | |||||
| return quote(fpath, safe) | |||||
| elif self.config.encode_safe is not None: | |||||
| return quote(fpath, self.config.encode_safe) | |||||
| else: | |||||
| return quote(fpath) | |||||
| return _encode_path(self.config.media_url, path, self._safe_chars(safe)) | |||||
| def full_url(self, path, safe=None): | def full_url(self, path, safe=None): | ||||
| """ | """ | ||||
| @@ -461,11 +461,9 @@ class Site(object): | |||||
| configuration and returns the appropriate url. The return value | configuration and returns the appropriate url. The return value | ||||
| is url encoded. | is url encoded. | ||||
| """ | """ | ||||
| if safe is None and self.config.encode_safe is not None: | |||||
| safe = self.config.encode_safe | |||||
| if urlparse.urlparse(path)[:2] != ("",""): | if urlparse.urlparse(path)[:2] != ("",""): | ||||
| return path | return path | ||||
| if self.is_media(path): | if self.is_media(path): | ||||
| relative_path = File(path).get_relative_path( | relative_path = File(path).get_relative_path( | ||||
| Folder(self.config.media_root)) | Folder(self.config.media_root)) | ||||
| @@ -1,4 +1,3 @@ | |||||
| # -*- coding: utf-8 -*- | |||||
| """ | """ | ||||
| Use nose | Use nose | ||||
| `$ pip install nose` | `$ pip install nose` | ||||
| @@ -49,6 +48,7 @@ class TestTextlinks(object): | |||||
| site.config.media_url = '/media' | site.config.media_url = '/media' | ||||
| tlink = File(site.content.source_folder.child('tlink.html')) | tlink = File(site.content.source_folder.child('tlink.html')) | ||||
| tlink.write(text % d) | tlink.write(text % d) | ||||
| print tlink.read_all() | |||||
| gen = Generator(site) | gen = Generator(site) | ||||
| gen.generate_all() | gen.generate_all() | ||||
| f = File(site.config.deploy_root_path.child(tlink.name)) | f = File(site.config.deploy_root_path.child(tlink.name)) | ||||
| @@ -56,5 +56,6 @@ class TestTextlinks(object): | |||||
| html = f.read_all() | html = f.read_all() | ||||
| assert html | assert html | ||||
| for name, path in d.items(): | for name, path in d.items(): | ||||
| assert quote(site.config.base_url + path) in html | |||||
| assert site.config.base_url + quote(path) in html | |||||
| assert '/media/img/hyde-logo.png' in html | assert '/media/img/hyde-logo.png' in html | ||||
| @@ -60,9 +60,19 @@ def test_node_full_url(): | |||||
| r = RootNode(TEST_SITE_ROOT.child_folder('content'), s) | r = RootNode(TEST_SITE_ROOT.child_folder('content'), s) | ||||
| assert not r.module | assert not r.module | ||||
| n = r.add_node(TEST_SITE_ROOT.child_folder('content/blog')) | n = r.add_node(TEST_SITE_ROOT.child_folder('content/blog')) | ||||
| assert n.full_url == quote('http://localhost/blog') | |||||
| assert n.full_url == 'http://localhost/blog' | |||||
| c = r.add_node(TEST_SITE_ROOT.child_folder('content/blog/2010/december')) | c = r.add_node(TEST_SITE_ROOT.child_folder('content/blog/2010/december')) | ||||
| assert c.full_url == quote('http://localhost/blog/2010/december') | |||||
| assert c.full_url == 'http://localhost/blog/2010/december' | |||||
| def test_node_full_url_quoted(): | |||||
| s = Site(TEST_SITE_ROOT) | |||||
| s.config.base_url = 'http://localhost' | |||||
| r = RootNode(TEST_SITE_ROOT.child_folder('content'), s) | |||||
| assert not r.module | |||||
| n = r.add_node(TEST_SITE_ROOT.child_folder('content/blo~g')) | |||||
| assert n.full_url == 'http://localhost/' + quote('blo~g') | |||||
| c = r.add_node(TEST_SITE_ROOT.child_folder('content/blo~g/2010/december')) | |||||
| assert c.full_url == 'http://localhost/' + quote('blo~g/2010/december') | |||||
| def test_node_relative_path(): | def test_node_relative_path(): | ||||
| s = Site(TEST_SITE_ROOT) | s = Site(TEST_SITE_ROOT) | ||||
| @@ -200,13 +210,15 @@ class TestSiteWithConfig(object): | |||||
| s = Site(self.SITE_PATH, config=self.config) | s = Site(self.SITE_PATH, config=self.config) | ||||
| s.load() | s.load() | ||||
| path = '".jpg' | path = '".jpg' | ||||
| assert s.content_url(path) == quote("/" + path) | |||||
| assert s.content_url(path) == "/" + quote(path) | |||||
| def test_content_url_encoding_safe(self): | def test_content_url_encoding_safe(self): | ||||
| s = Site(self.SITE_PATH, config=self.config) | s = Site(self.SITE_PATH, config=self.config) | ||||
| s.load() | s.load() | ||||
| path = '".jpg/abc' | path = '".jpg/abc' | ||||
| assert s.content_url(path, "") == quote("/" + path, "") | |||||
| print s.content_url(path, "") | |||||
| print "/" + quote(path, "") | |||||
| assert s.content_url(path, "") == "/" + quote(path, "") | |||||
| def test_media_url(self): | def test_media_url(self): | ||||
| s = Site(self.SITE_PATH, config=self.config) | s = Site(self.SITE_PATH, config=self.config) | ||||
| @@ -2,4 +2,4 @@ | |||||
| """ | """ | ||||
| Handles hyde version. | Handles hyde version. | ||||
| """ | """ | ||||
| __version__ = '0.8.7a8' | |||||
| __version__ = '0.8.7a9' | |||||