- 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' |