comparison piecrust/routing.py @ 520:bab91fcef741

bake/serve: Improve support for unicode, add slugification options. * Add slugification options for taxonomies. * Sort out some unicode support problems on OSX. * Add tests.
author Ludovic Chabant <ludovic@chabant.com>
date Tue, 28 Jul 2015 18:34:21 -0700
parents 16e705c58cae
children daf8df5ade7d
comparison
equal deleted inserted replaced
519:9d1a89cd8146 520:bab91fcef741
1 import re 1 import re
2 import os.path 2 import os.path
3 import copy 3 import copy
4 import logging 4 import logging
5 import urllib.parse
6 import unidecode
5 7
6 8
7 logger = logging.getLogger(__name__) 9 logger = logging.getLogger(__name__)
8 10
9 11
28 30
29 31
30 class IRouteMetadataProvider(object): 32 class IRouteMetadataProvider(object):
31 def getRouteMetadata(self): 33 def getRouteMetadata(self):
32 raise NotImplementedError() 34 raise NotImplementedError()
35
36
37 SLUGIFY_ENCODE = 1
38 SLUGIFY_TRANSLITERATE = 2
39 SLUGIFY_LOWERCASE = 4
40 SLUGIFY_DOT_TO_DASH = 8
41
42
43 re_first_dot_to_dash = re.compile(r'^\.+')
44 re_dot_to_dash = re.compile(r'\.+')
45
46
47 def _parse_slugify_mode(value):
48 mapping = {
49 'encode': SLUGIFY_ENCODE,
50 'transliterate': SLUGIFY_TRANSLITERATE,
51 'lowercase': SLUGIFY_LOWERCASE,
52 'dot_to_dash': SLUGIFY_DOT_TO_DASH}
53 mode = 0
54 for v in value.split(','):
55 f = mapping.get(v.strip())
56 if f is None:
57 if v == 'iconv':
58 raise Exception("'iconv' is not supported as a slugify mode "
59 "in PieCrust2. Use 'transliterate'.")
60 raise Exception("Unknown slugify flag: %s" % v)
61 mode |= f
62 return mode
33 63
34 64
35 class Route(object): 65 class Route(object):
36 """ Information about a route for a PieCrust application. 66 """ Information about a route for a PieCrust application.
37 Each route defines the "shape" of an URL and how it maps to 67 Each route defines the "shape" of an URL and how it maps to
41 self.app = app 71 self.app = app
42 72
43 self.source_name = cfg['source'] 73 self.source_name = cfg['source']
44 self.taxonomy_name = cfg.get('taxonomy') 74 self.taxonomy_name = cfg.get('taxonomy')
45 self.taxonomy_term_sep = cfg.get('term_separator', '/') 75 self.taxonomy_term_sep = cfg.get('term_separator', '/')
76 self.slugify_mode = _parse_slugify_mode(
77 cfg.get('slugify_mode', 'encode,lowercase'))
46 78
47 self.pretty_urls = app.config.get('site/pretty_urls') 79 self.pretty_urls = app.config.get('site/pretty_urls')
48 self.trailing_slash = app.config.get('site/trailing_slash') 80 self.trailing_slash = app.config.get('site/trailing_slash')
49 self.show_debug_info = app.config.get('site/show_debug_info') 81 self.show_debug_info = app.config.get('site/show_debug_info')
50 self.pagination_suffix_format = app.config.get( 82 self.pagination_suffix_format = app.config.get(
183 if suffix: 215 if suffix:
184 uri = base_uri + suffix + ext 216 uri = base_uri + suffix + ext
185 else: 217 else:
186 uri = base_uri + ext 218 uri = base_uri + ext
187 219
188 uri = self.uri_root + uri 220 uri = urllib.parse.quote(self.uri_root + uri)
189 221
190 if self.show_debug_info: 222 if self.show_debug_info:
191 uri += '?!debug' 223 uri += '?!debug'
192 224
193 return uri 225 return uri
205 if self.taxonomy_term_sep in all_values: 237 if self.taxonomy_term_sep in all_values:
206 return tuple(all_values.split(self.taxonomy_term_sep)) 238 return tuple(all_values.split(self.taxonomy_term_sep))
207 return all_values 239 return all_values
208 240
209 def slugifyTaxonomyTerm(self, term): 241 def slugifyTaxonomyTerm(self, term):
210 #TODO: add options for transliterating and combining terms.
211 if isinstance(term, tuple): 242 if isinstance(term, tuple):
212 return '/'.join(term) 243 return self.taxonomy_term_sep.join(
244 map(self._slugifyOne, term))
245 return self._slugifyOne(term)
246
247 def _slugifyOne(self, term):
248 if self.slugify_mode & SLUGIFY_TRANSLITERATE:
249 term = unidecode.unidecode(term)
250 if self.slugify_mode & SLUGIFY_LOWERCASE:
251 term = term.lower()
252 if self.slugify_mode & SLUGIFY_DOT_TO_DASH:
253 term = re_first_dot_to_dash.sub('', term)
254 term = re_dot_to_dash.sub('-', term)
213 return term 255 return term
214 256
215 def _uriFormatRepl(self, m): 257 def _uriFormatRepl(self, m):
216 name = m.group('name') 258 name = m.group('name')
217 #TODO: fix this hard-coded shit 259 #TODO: fix this hard-coded shit