Conversion: Sort the CSS rules in the output stylesheet using a "natural" sort algorithm, so that calibre2 sorts before calibre10. Fixes #1265175 [[Feature request] Alphanumeric sort of classes in stylesheet](https://bugs.launchpad.net/calibre/+bug/1265175)

This commit is contained in:
Kovid Goyal 2014-01-01 10:20:10 +05:30
parent f092a643ae
commit 3bfd3bc07f
2 changed files with 27 additions and 3 deletions

View File

@ -19,6 +19,7 @@ from calibre.ebooks.oeb.base import (XHTML, XHTML_NS, CSS_MIME, OEB_STYLES,
namespace, barename, XPath)
from calibre.ebooks.oeb.stylizer import Stylizer
from calibre.utils.filenames import ascii_filename, ascii_text
from calibre.utils.icu import numeric_sort_key
COLLAPSE = re.compile(r'[ \t\r\n\v]+')
STRIPNUM = re.compile(r'[-0-9]+$')
@ -459,7 +460,7 @@ class CSSFlattener(object):
keep_classes = set()
if cssdict:
items = sorted(cssdict.items())
items = sorted(cssdict.iteritems())
css = u';\n'.join(u'%s: %s' % (key, val) for key, val in items)
classes = node.get('class', '').strip() or 'calibre'
klass = ascii_text(STRIPNUM.sub('', classes.split()[0].replace('_', '')))
@ -577,7 +578,7 @@ class CSSFlattener(object):
body = html.find(XHTML('body'))
fsize = self.context.dest.fbase
self.flatten_node(body, stylizer, names, styles, pseudo_styles, fsize, item.id)
items = sorted([(key, val) for (val, key) in styles.items()])
items = sorted(((key, val) for (val, key) in styles.iteritems()), key=lambda x:numeric_sort_key(x[0]))
# :hover must come after link and :active must come after :hover
psels = sorted(pseudo_styles.iterkeys(), key=lambda x :
{'hover':1, 'active':2}.get(x, 0))

View File

@ -12,7 +12,7 @@ from functools import partial
from calibre.constants import plugins
from calibre.utils.config_base import tweaks
_icu = _collator = _primary_collator = _sort_collator = None
_icu = _collator = _primary_collator = _sort_collator = _numeric_collator = None
_locale = None
_none = u''
@ -90,6 +90,29 @@ def icu_sort_key(collator, obj):
obj = obj.replace(b'\0', b'')
return _sort_collator.sort_key(obj)
def numeric_collator():
global _numeric_collator
_numeric_collator = _collator.clone()
_numeric_collator.strength = _icu.UCOL_SECONDARY
_numeric_collator.numeric = True
return _numeric_collator
def numeric_sort_key(obj):
'Uses natural sorting for numbers inside strings so something2 will sort before something10'
if not obj:
return _none2
try:
try:
return _numeric_collator.sort_key(obj)
except AttributeError:
return numeric_collator().sort_key(obj)
except TypeError:
if isinstance(obj, unicode):
obj = obj.replace(u'\0', u'')
else:
obj = obj.replace(b'\0', b'')
return _numeric_collator.sort_key(obj)
def icu_change_case(upper, locale, obj):
func = _icu.upper if upper else _icu.lower
try: