mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
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:
parent
d23532e499
commit
d28114bde1
BIN
resources/images/sort.png
Normal file
BIN
resources/images/sort.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
@ -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
|
||||||
|
@ -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 (
|
||||||
|
@ -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)
|
||||||
|
@ -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'))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user