mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Move panose-1 error nuking to new CSS checking code
Fixes #2052427 [After converting to epub and running a check-up for errors on the epub editor, always the following message appears: Unexpected unknown property “panose-1” (property-no-unknown).](https://bugs.launchpad.net/calibre/+bug/2052427)
This commit is contained in:
parent
1f1e08980c
commit
a725dd21ac
@ -48,6 +48,9 @@ def message_to_error(message, name, line_offset, rule_metadata):
|
|||||||
cls = CSSParseError
|
cls = CSSParseError
|
||||||
else:
|
else:
|
||||||
cls = CSSError if message.get('severity') == 'error' else CSSWarning
|
cls = CSSError if message.get('severity') == 'error' else CSSWarning
|
||||||
|
if message.get('rule') == 'property-no-unknown' and 'panose-1' in message.get('text', ''):
|
||||||
|
# suppress panose-1 it is allowed in CSSS 2.1 and generated by calibre conversation
|
||||||
|
return
|
||||||
title = message.get('text') or _('Unknown error')
|
title = message.get('text') or _('Unknown error')
|
||||||
title = title.rpartition('(')[0].strip()
|
title = title.rpartition('(')[0].strip()
|
||||||
line = as_int_or_none(message.get('line'))
|
line = as_int_or_none(message.get('line'))
|
||||||
|
@ -5,22 +5,22 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from lxml.etree import XMLSyntaxError
|
from lxml.etree import XMLSyntaxError
|
||||||
|
|
||||||
from calibre import force_unicode, human_readable, prepare_string_for_xml
|
from calibre import human_readable, prepare_string_for_xml
|
||||||
from calibre.ebooks.chardet import replace_encoding_declarations, find_declared_encoding
|
from calibre.ebooks.chardet import find_declared_encoding, replace_encoding_declarations
|
||||||
from calibre.utils.xml_parse import safe_xml_fromstring
|
|
||||||
from calibre.ebooks.html_entities import html5_entities
|
from calibre.ebooks.html_entities import html5_entities
|
||||||
|
from calibre.ebooks.oeb.base import OEB_DOCS, URL_SAFE, XHTML, XHTML_NS, urlquote
|
||||||
|
from calibre.ebooks.oeb.polish.check.base import INFO, WARN, BaseError
|
||||||
from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style as fix_style_tag
|
from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style as fix_style_tag
|
||||||
from calibre.ebooks.oeb.polish.utils import PositionFinder, guess_type
|
from calibre.ebooks.oeb.polish.utils import PositionFinder, guess_type
|
||||||
from calibre.ebooks.oeb.polish.check.base import BaseError, WARN, ERROR, INFO
|
from calibre.utils.xml_parse import safe_xml_fromstring
|
||||||
from calibre.ebooks.oeb.base import OEB_DOCS, XHTML_NS, urlquote, URL_SAFE, XHTML
|
from polyglot.builtins import error_message, iteritems
|
||||||
from polyglot.builtins import iteritems, error_message
|
|
||||||
|
|
||||||
HTML_ENTITTIES = frozenset(html5_entities)
|
HTML_ENTITTIES = frozenset(html5_entities)
|
||||||
XML_ENTITIES = {'lt', 'gt', 'amp', 'apos', 'quot'}
|
XML_ENTITIES = {'lt', 'gt', 'amp', 'apos', 'quot'}
|
||||||
ALL_ENTITIES = HTML_ENTITTIES | XML_ENTITIES
|
ALL_ENTITIES = HTML_ENTITTIES | XML_ENTITIES
|
||||||
|
fix_style_tag
|
||||||
|
|
||||||
replace_pat = re.compile('&(%s);' % '|'.join(re.escape(x) for x in sorted(HTML_ENTITTIES - XML_ENTITIES)))
|
replace_pat = re.compile('&(%s);' % '|'.join(re.escape(x) for x in sorted(HTML_ENTITTIES - XML_ENTITIES)))
|
||||||
mismatch_pat = re.compile(r'tag mismatch:.+?line (\d+).+?line \d+')
|
mismatch_pat = re.compile(r'tag mismatch:.+?line (\d+).+?line \d+')
|
||||||
@ -305,40 +305,6 @@ def check_xml_parsing(name, mt, raw):
|
|||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
class CSSError(BaseError):
|
|
||||||
|
|
||||||
is_parsing_error = True
|
|
||||||
|
|
||||||
def __init__(self, level, msg, name, line, col):
|
|
||||||
self.level = level
|
|
||||||
prefix = 'CSS: '
|
|
||||||
BaseError.__init__(self, prefix + msg, name, line, col)
|
|
||||||
if level == WARN:
|
|
||||||
self.HELP = _('This CSS construct is not recognized. That means that it'
|
|
||||||
' most likely will not work on reader devices. Consider'
|
|
||||||
' replacing it with something else.')
|
|
||||||
else:
|
|
||||||
self.HELP = _('Some reader programs are very'
|
|
||||||
' finicky about CSS stylesheets and will ignore the whole'
|
|
||||||
' sheet if there is an error. These errors can often'
|
|
||||||
' be fixed automatically, however, automatic fixing will'
|
|
||||||
' typically remove unrecognized items, instead of correcting them.')
|
|
||||||
self.INDIVIDUAL_FIX = _('Try to fix parsing errors in this stylesheet automatically')
|
|
||||||
|
|
||||||
def __call__(self, container):
|
|
||||||
root = container.parsed(self.name)
|
|
||||||
container.dirty(self.name)
|
|
||||||
if container.mime_map[self.name] in OEB_DOCS:
|
|
||||||
for style in root.xpath('//*[local-name()="style"]'):
|
|
||||||
if style.get('type', 'text/css') == 'text/css' and style.text and style.text.strip():
|
|
||||||
fix_style_tag(container, style)
|
|
||||||
for elem in root.xpath('//*[@style]'):
|
|
||||||
raw = elem.get('style')
|
|
||||||
if raw:
|
|
||||||
elem.set('style', force_unicode(container.parse_css(raw, is_declaration=True).cssText, 'utf-8').replace('\n', ' '))
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
pos_pats = (re.compile(r'\[(\d+):(\d+)'), re.compile(r'(\d+), (\d+)\)'))
|
pos_pats = (re.compile(r'\[(\d+):(\d+)'), re.compile(r'(\d+), (\d+)\)'))
|
||||||
|
|
||||||
|
|
||||||
@ -428,41 +394,6 @@ class BareTextInBody(BaseError):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class ErrorHandler:
|
|
||||||
|
|
||||||
' Replacement logger to get useful error/warning info out of css_parser during parsing '
|
|
||||||
|
|
||||||
def __init__(self, name):
|
|
||||||
# may be disabled during setting of known valid items
|
|
||||||
self.name = name
|
|
||||||
self.errors = []
|
|
||||||
|
|
||||||
def __noop(self, *args, **kwargs):
|
|
||||||
pass
|
|
||||||
info = debug = setLevel = getEffectiveLevel = addHandler = removeHandler = __noop
|
|
||||||
|
|
||||||
def __handle(self, level, *args):
|
|
||||||
msg = ' '.join(map(str, args))
|
|
||||||
line = col = None
|
|
||||||
for pat in pos_pats:
|
|
||||||
m = pat.search(msg)
|
|
||||||
if m is not None:
|
|
||||||
line, col = int(m.group(1)), int(m.group(2))
|
|
||||||
if msg and line is not None:
|
|
||||||
# Ignore error messages with no line numbers as these are usually
|
|
||||||
# summary messages for an underlying error with a line number
|
|
||||||
if 'panose-1' in msg and 'unknown property name' in msg.lower():
|
|
||||||
return # panose-1 is allowed in CSS 2.1 and is generated by calibre
|
|
||||||
self.errors.append(CSSError(level, msg, self.name, line, col))
|
|
||||||
|
|
||||||
def error(self, *args):
|
|
||||||
self.__handle(ERROR, *args)
|
|
||||||
|
|
||||||
def warn(self, *args):
|
|
||||||
self.__handle(WARN, *args)
|
|
||||||
warning = warn
|
|
||||||
|
|
||||||
|
|
||||||
def check_filenames(container):
|
def check_filenames(container):
|
||||||
errors = []
|
errors = []
|
||||||
all_names = set(container.name_path_map) - container.names_that_must_not_be_changed
|
all_names = set(container.name_path_map) - container.names_that_must_not_be_changed
|
||||||
|
Loading…
x
Reference in New Issue
Block a user