Edit Book: A new tool to sort the rules in a CSS stylesheet. To use it add it to the toolbar for CSS editors

This commit is contained in:
Kovid Goyal 2016-09-07 12:46:06 +05:30
parent d23532e499
commit d28114bde1
5 changed files with 47 additions and 2 deletions

BIN
resources/images/sort.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -16,6 +16,7 @@ from calibre import force_unicode
from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS
from calibre.ebooks.oeb.normalize_css import normalize_filter_css, normalizers from calibre.ebooks.oeb.normalize_css import normalize_filter_css, normalizers
from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style
from calibre.utils.icu import numeric_sort_key
from css_selectors import Select, SelectorError from css_selectors import Select, SelectorError
@ -324,3 +325,37 @@ def remove_property_value(prop, predicate):
x = x.replace(v.cssText, '').strip() x = x.replace(v.cssText, '').strip()
prop.propertyValue.cssText = x prop.propertyValue.cssText = x
return bool(removed_vals) return bool(removed_vals)
RULE_PRIORITIES = {t:i for i, t in enumerate((CSSRule.COMMENT, CSSRule.CHARSET_RULE, CSSRule.IMPORT_RULE, CSSRule.NAMESPACE_RULE))}
def sort_sheet(container, sheet_or_text):
''' Sort the rules in a stylesheet. Note that in the general case this can
change the effective styles, but for most common sheets, it should be safe.
'''
sheet = container.parse_css(sheet_or_text) if isinstance(sheet_or_text, unicode) else sheet_or_text
def text_sort_key(x):
return numeric_sort_key(unicode(x or ''))
def selector_sort_key(x):
return (x.specificity, text_sort_key(x.selectorText))
def rule_sort_key(rule):
primary = RULE_PRIORITIES.get(rule.type, len(RULE_PRIORITIES))
secondary = text_sort_key(getattr(rule, 'atkeyword', '') or '')
tertiary = None
if rule.type == CSSRule.STYLE_RULE:
primary += 1
selectors = sorted(rule.selectorList, key=selector_sort_key)
tertiary = selector_sort_key(selectors[0])
rule.selectorText = ', '.join(s.selectorText for s in selectors)
elif rule.type == CSSRule.FONT_FACE_RULE:
try:
tertiary = text_sort_key(rule.style.getPropertyValue('font-family'))
except Exception:
pass
return primary, secondary, tertiary
sheet.cssRules.sort(key=rule_sort_key)
return sheet

View File

@ -58,7 +58,7 @@ d['global_tools_toolbar'] = [
] ]
d['global_plugins_toolbar'] = [] d['global_plugins_toolbar'] = []
d['editor_common_toolbar'] = [('editor-' + x) if x else None for x in ('undo', 'redo', None, 'cut', 'copy', 'paste', 'smart-comment')] d['editor_common_toolbar'] = [('editor-' + x) if x else None for x in ('undo', 'redo', None, 'cut', 'copy', 'paste', 'smart-comment')]
d['editor_css_toolbar'] = ['pretty-current', 'insert-image'] d['editor_css_toolbar'] = ['pretty-current', 'sort-css', 'insert-image']
d['editor_xml_toolbar'] = ['pretty-current', 'insert-tag'] d['editor_xml_toolbar'] = ['pretty-current', 'insert-tag']
d['editor_html_toolbar'] = ['fix-html-current', 'pretty-current', 'insert-image', 'insert-hyperlink', 'insert-tag', 'change-paragraph'] d['editor_html_toolbar'] = ['fix-html-current', 'pretty-current', 'insert-image', 'insert-hyperlink', 'insert-tag', 'change-paragraph']
d['editor_format_toolbar'] = [('format-text-' + x) if x else x for x in ( d['editor_format_toolbar'] = [('format-text-' + x) if x else x for x in (

View File

@ -17,7 +17,7 @@ from PyQt5.Qt import (
QColorDialog, QTimer, pyqtSignal) QColorDialog, QTimer, pyqtSignal)
from calibre import prepare_string_for_xml from calibre import prepare_string_for_xml
from calibre.gui2.tweak_book import tprefs, TOP from calibre.gui2.tweak_book import tprefs, TOP, current_container
from calibre.gui2.tweak_book.completion.popup import CompletionPopup from calibre.gui2.tweak_book.completion.popup import CompletionPopup
from calibre.gui2.tweak_book.editor import ( from calibre.gui2.tweak_book.editor import (
SYNTAX_PROPERTY, SPELL_PROPERTY, SPELL_LOCALE_PROPERTY, store_locale, LINK_PROPERTY) SYNTAX_PROPERTY, SPELL_PROPERTY, SPELL_LOCALE_PROPERTY, store_locale, LINK_PROPERTY)
@ -332,6 +332,14 @@ class TextEdit(PlainTextEdit):
from calibre.gui2.tweak_book.editor.comments import smart_comment from calibre.gui2.tweak_book.editor.comments import smart_comment
smart_comment(self, self.syntax) smart_comment(self, self.syntax)
def sort_css(self):
from calibre.gui2.dialogs.confirm_delete import confirm
if confirm(_('Sorting CSS rules can in rare cases change the effective styles applied to the book.'
' Are you sure you want to proceed?'), 'edit-book-confirm-sort-css', parent=self, config_set=tprefs):
from calibre.ebooks.oeb.polish.css import sort_sheet
text = sort_sheet(current_container(), self.toPlainText()).cssText
self.setPlainText(text)
def find(self, pat, wrap=False, marked=False, complete=False, save_match=None): def find(self, pat, wrap=False, marked=False, complete=False, save_match=None):
if marked: if marked:
return self.find_in_marked(pat, wrap=wrap, save_match=save_match) return self.find_in_marked(pat, wrap=wrap, save_match=save_match)

View File

@ -80,6 +80,8 @@ def register_text_editor_actions(_reg, palette):
ac = reg('format-justify-fill.png', _('&Justify'), ('format_text', 'justify_justify'), 'format-text-justify-fill', (), _('Justify')) ac = reg('format-justify-fill.png', _('&Justify'), ('format_text', 'justify_justify'), 'format-text-justify-fill', (), _('Justify'))
ac.setToolTip(_('<h3>Justify</h3>Align the paragraph to both the left and right margins')) ac.setToolTip(_('<h3>Justify</h3>Align the paragraph to both the left and right margins'))
ac = reg('sort.png', _('&Sort style rules'), ('sort_css',), 'editor-sort-css', (),
_('Sort the style rules'), syntaxes=('css',))
ac = reg('view-image.png', _('&Insert image'), ('insert_resource', 'image'), 'insert-image', (), ac = reg('view-image.png', _('&Insert image'), ('insert_resource', 'image'), 'insert-image', (),
_('Insert an image into the text'), syntaxes=('html', 'css')) _('Insert an image into the text'), syntaxes=('html', 'css'))
ac.setToolTip(_('<h3>Insert image</h3>Insert an image into the text')) ac.setToolTip(_('<h3>Insert image</h3>Insert an image into the text'))