mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
d4121a7cfe
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.6.6'
|
__version__ = '0.6.7'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -42,7 +42,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
WINDOWS_MAIN_MEM = None
|
WINDOWS_MAIN_MEM = None
|
||||||
WINDOWS_CARD_A_MEM = None
|
WINDOWS_CARD_A_MEM = None
|
||||||
WINDOWS_CARD_B_MEM = None
|
WINDOWS_CARD_B_MEM = None
|
||||||
ALLOW_NO_MAIN_MEMORY = False
|
|
||||||
|
|
||||||
# The following are used by the check_ioreg_line method and can be either:
|
# The following are used by the check_ioreg_line method and can be either:
|
||||||
# None, a string, a list of strings or a compiled regular expression
|
# None, a string, a list of strings or a compiled regular expression
|
||||||
@ -267,9 +266,6 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
drives['cardb'] = self.windows_get_drive_prefix(drive)
|
drives['cardb'] = self.windows_get_drive_prefix(drive)
|
||||||
elif self.windows_match_device(drive, 'WINDOWS_MAIN_MEM') and not drives.get('main', None):
|
elif self.windows_match_device(drive, 'WINDOWS_MAIN_MEM') and not drives.get('main', None):
|
||||||
drives['main'] = self.windows_get_drive_prefix(drive)
|
drives['main'] = self.windows_get_drive_prefix(drive)
|
||||||
if not self.ALLOW_NO_MAIN_MEMORY:
|
|
||||||
raise DeviceError('Failed to find the drive corresponding'
|
|
||||||
' to the main memory')
|
|
||||||
|
|
||||||
if 'main' in drives.keys() and 'carda' in drives.keys() and \
|
if 'main' in drives.keys() and 'carda' in drives.keys() and \
|
||||||
'cardb' in drives.keys():
|
'cardb' in drives.keys():
|
||||||
@ -277,7 +273,7 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
|
|
||||||
drives = self.windows_open_callback(drives)
|
drives = self.windows_open_callback(drives)
|
||||||
|
|
||||||
if 'main' not in drives:
|
if drives.get('main', None) is None:
|
||||||
raise DeviceError(
|
raise DeviceError(
|
||||||
_('Unable to detect the %s disk drive. Try rebooting.') %
|
_('Unable to detect the %s disk drive. Try rebooting.') %
|
||||||
self.__class__.__name__)
|
self.__class__.__name__)
|
||||||
|
@ -317,7 +317,13 @@ class MobiReader(object):
|
|||||||
if root.xpath('descendant::p/descendant::p'):
|
if root.xpath('descendant::p/descendant::p'):
|
||||||
from lxml.html import soupparser
|
from lxml.html import soupparser
|
||||||
self.log.warning('Malformed markup, parsing using BeautifulSoup')
|
self.log.warning('Malformed markup, parsing using BeautifulSoup')
|
||||||
|
try:
|
||||||
root = soupparser.fromstring(self.processed_html)
|
root = soupparser.fromstring(self.processed_html)
|
||||||
|
except Exception, err:
|
||||||
|
self.log.warning('MOBI markup appears to contain random bytes. Stripping.')
|
||||||
|
self.processed_html = self.remove_random_bytes(self.processed_html)
|
||||||
|
root = soupparser.fromstring(self.processed_html)
|
||||||
|
|
||||||
|
|
||||||
if root.tag != 'html':
|
if root.tag != 'html':
|
||||||
self.log.warn('File does not have opening <html> tag')
|
self.log.warn('File does not have opening <html> tag')
|
||||||
@ -457,7 +463,7 @@ class MobiReader(object):
|
|||||||
self.processed_html = self.processed_html.replace('<mbp: ', '<mbp:')
|
self.processed_html = self.processed_html.replace('<mbp: ', '<mbp:')
|
||||||
|
|
||||||
def remove_random_bytes(self, html):
|
def remove_random_bytes(self, html):
|
||||||
return re.sub('\x14|\x15|\x1c|\x1d|\xef|\x12|\x13|\xec',
|
return re.sub('\x14|\x15|\x19|\x1c|\x1d|\xef|\x12|\x13|\xec|\x08',
|
||||||
'', html)
|
'', html)
|
||||||
|
|
||||||
def ensure_unit(self, raw, unit='px'):
|
def ensure_unit(self, raw, unit='px'):
|
||||||
@ -492,11 +498,12 @@ class MobiReader(object):
|
|||||||
styles.append(style)
|
styles.append(style)
|
||||||
if attrib.has_key('height'):
|
if attrib.has_key('height'):
|
||||||
height = attrib.pop('height').strip()
|
height = attrib.pop('height').strip()
|
||||||
if height:
|
if height and '<' not in height and '>' not in height and \
|
||||||
|
re.search(r'\d+', height):
|
||||||
styles.append('margin-top: %s' % self.ensure_unit(height))
|
styles.append('margin-top: %s' % self.ensure_unit(height))
|
||||||
if attrib.has_key('width'):
|
if attrib.has_key('width'):
|
||||||
width = attrib.pop('width').strip()
|
width = attrib.pop('width').strip()
|
||||||
if width:
|
if width and re.search(r'\d+', width):
|
||||||
styles.append('text-indent: %s' % self.ensure_unit(width))
|
styles.append('text-indent: %s' % self.ensure_unit(width))
|
||||||
if width.startswith('-'):
|
if width.startswith('-'):
|
||||||
styles.append('margin-left: %s' % self.ensure_unit(width[1:]))
|
styles.append('margin-left: %s' % self.ensure_unit(width[1:]))
|
||||||
@ -714,6 +721,9 @@ class MobiReader(object):
|
|||||||
self.processed_html += self.mobi_html[pos:end] + (anchor % oend)
|
self.processed_html += self.mobi_html[pos:end] + (anchor % oend)
|
||||||
pos = end
|
pos = end
|
||||||
self.processed_html += self.mobi_html[pos:]
|
self.processed_html += self.mobi_html[pos:]
|
||||||
|
# Remove anchors placed inside entities
|
||||||
|
self.processed_html = re.sub(r'&([^;]*?)(<a id="filepos\d+"></a>)([^;]*);',
|
||||||
|
r'&\1\3;\2', self.processed_html)
|
||||||
|
|
||||||
|
|
||||||
def extract_images(self, processed_records, output_dir):
|
def extract_images(self, processed_records, output_dir):
|
||||||
|
@ -14,6 +14,9 @@ class LinearizeTables(object):
|
|||||||
for x in root.xpath('//h:table|//h:td|//h:tr|//h:th',
|
for x in root.xpath('//h:table|//h:td|//h:tr|//h:th',
|
||||||
namespaces=XPNSMAP):
|
namespaces=XPNSMAP):
|
||||||
x.tag = 'div'
|
x.tag = 'div'
|
||||||
|
for attr in ('valign', 'colspan', 'rowspan', 'width', 'halign'):
|
||||||
|
if attr in x.attrib:
|
||||||
|
del x.attrib[attr]
|
||||||
|
|
||||||
def __call__(self, oeb, context):
|
def __call__(self, oeb, context):
|
||||||
for x in oeb.manifest.items:
|
for x in oeb.manifest.items:
|
||||||
|
@ -1,26 +1,25 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import urllib, re, traceback
|
import traceback
|
||||||
|
|
||||||
from PyQt4.QtCore import QThread, SIGNAL
|
from PyQt4.QtCore import QThread, SIGNAL
|
||||||
|
import mechanize
|
||||||
|
|
||||||
from calibre import __version__, __appname__
|
from calibre.constants import __version__
|
||||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
from calibre import browser
|
||||||
|
|
||||||
|
URL = 'http://status.calibre-ebook.com/latest'
|
||||||
|
|
||||||
class CheckForUpdates(QThread):
|
class CheckForUpdates(QThread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
src = urllib.urlopen('http://pypi.python.org/pypi/'+__appname__).read()
|
br = browser()
|
||||||
soup = BeautifulSoup(src)
|
req = mechanize.Request(URL)
|
||||||
meta = soup.find('link', rel='meta', title='DOAP')
|
req.add_header('CALIBRE_VERSION', __version__)
|
||||||
if meta:
|
version = br.open(req).read().strip()
|
||||||
src = meta['href']
|
if version and version != __version__:
|
||||||
match = re.search(r'version=(\S+)', src)
|
|
||||||
if match:
|
|
||||||
version = match.group(1)
|
|
||||||
if version != __version__:
|
|
||||||
self.emit(SIGNAL('update_found(PyQt_PyObject)'), version)
|
self.emit(SIGNAL('update_found(PyQt_PyObject)'), version)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -4,9 +4,9 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre 0.6.6\n"
|
"Project-Id-Version: calibre 0.6.7\n"
|
||||||
"POT-Creation-Date: 2009-08-13 12:30+MDT\n"
|
"POT-Creation-Date: 2009-08-14 21:48+MDT\n"
|
||||||
"PO-Revision-Date: 2009-08-13 12:30+MDT\n"
|
"PO-Revision-Date: 2009-08-14 21:48+MDT\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: LANGUAGE\n"
|
"Language-Team: LANGUAGE\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -118,7 +118,7 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:404
|
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:404
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:874
|
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:874
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1000
|
#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1000
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:264
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:265
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database.py:917
|
#: /home/kovid/work/calibre/src/calibre/library/database.py:917
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:655
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:655
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:667
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:667
|
||||||
@ -127,9 +127,9 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1429
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1429
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1431
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1431
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1515
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1515
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1604
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1606
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1632
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1634
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1683
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1685
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:309
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:309
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:373
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:373
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
@ -1465,7 +1465,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1308
|
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1308
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/htmltoc.py:15
|
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/htmltoc.py:15
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:48
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:51
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:168
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:168
|
||||||
msgid "Table of Contents"
|
msgid "Table of Contents"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2240,7 +2240,7 @@ msgid "&Monospaced font family:"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:23
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata.py:23
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:142
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:145
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:169
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:169
|
||||||
msgid "Metadata"
|
msgid "Metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3745,7 +3745,7 @@ msgid "Scheduled"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:240
|
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:240
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:218
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:221
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -4346,7 +4346,7 @@ msgid "<b>No matches</b> for the search phrase <i>%s</i> were found."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/lrf_renderer/main.py:157
|
#: /home/kovid/work/calibre/src/calibre/gui2/lrf_renderer/main.py:157
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:417
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:420
|
||||||
msgid "No matches found"
|
msgid "No matches found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5185,7 +5185,7 @@ msgid "Options to customize the ebook viewer"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:59
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/documentview.py:59
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:646
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:649
|
||||||
msgid "Remember last used window size"
|
msgid "Remember last used window size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -5234,95 +5234,95 @@ msgstr ""
|
|||||||
msgid "The standard font type"
|
msgid "The standard font type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:143
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:146
|
||||||
msgid "Book format"
|
msgid "Book format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:166
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:169
|
||||||
msgid "Go to..."
|
msgid "Go to..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:207
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:210
|
||||||
msgid "Position in book"
|
msgid "Position in book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:208
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:211
|
||||||
msgid "/Unknown"
|
msgid "/Unknown"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:213
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:216
|
||||||
msgid "Go to a reference. To get reference numbers, use the reference mode."
|
msgid "Go to a reference. To get reference numbers, use the reference mode."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:219
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:222
|
||||||
msgid "Search for text in book"
|
msgid "Search for text in book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:282
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:285
|
||||||
msgid "Print Preview"
|
msgid "Print Preview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:377
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:380
|
||||||
msgid "Choose ebook"
|
msgid "Choose ebook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:378
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:381
|
||||||
msgid "Ebooks"
|
msgid "Ebooks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:397
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:400
|
||||||
msgid "Add bookmark"
|
msgid "Add bookmark"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:397
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:400
|
||||||
msgid "Enter title for bookmark:"
|
msgid "Enter title for bookmark:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:418
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:421
|
||||||
msgid "No matches found for: %s"
|
msgid "No matches found for: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:458
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:461
|
||||||
msgid "Loading flow..."
|
msgid "Loading flow..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:485
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:488
|
||||||
msgid "Laying out %s"
|
msgid "Laying out %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:514
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:517
|
||||||
msgid "Manage Bookmarks"
|
msgid "Manage Bookmarks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:549
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:552
|
||||||
msgid "Loading ebook..."
|
msgid "Loading ebook..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:557
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:560
|
||||||
msgid "DRM Error"
|
msgid "DRM Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:558
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:561
|
||||||
msgid "<p>This book is protected by <a href=\"%s\">DRM</a>"
|
msgid "<p>This book is protected by <a href=\"%s\">DRM</a>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:562
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:565
|
||||||
msgid "Could not open ebook"
|
msgid "Could not open ebook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:636
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:639
|
||||||
msgid "Options to control the ebook viewer"
|
msgid "Options to control the ebook viewer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:643
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:646
|
||||||
msgid "If specified, viewer window will try to come to the front when started."
|
msgid "If specified, viewer window will try to come to the front when started."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:648
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:651
|
||||||
msgid "Print javascript alert and console messages to the console"
|
msgid "Print javascript alert and console messages to the console"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:654
|
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:657
|
||||||
msgid ""
|
msgid ""
|
||||||
"%prog [options] file\n"
|
"%prog [options] file\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -5706,64 +5706,64 @@ msgstr ""
|
|||||||
msgid "Path to the calibre library. Default is to use the path stored in the settings."
|
msgid "Path to the calibre library. Default is to use the path stored in the settings."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:188
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:189
|
||||||
msgid ""
|
msgid ""
|
||||||
"%prog list [options]\n"
|
"%prog list [options]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"List the books available in the calibre database.\n"
|
"List the books available in the calibre database.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:196
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:197
|
||||||
msgid ""
|
msgid ""
|
||||||
"The fields to display when listing books in the database. Should be a comma separated list of fields.\n"
|
"The fields to display when listing books in the database. Should be a comma separated list of fields.\n"
|
||||||
"Available fields: %s\n"
|
"Available fields: %s\n"
|
||||||
"Default: %%default. The special field \"all\" can be used to select all fields. Only has effect in the text output format."
|
"Default: %%default. The special field \"all\" can be used to select all fields. Only has effect in the text output format."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:198
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:199
|
||||||
msgid ""
|
msgid ""
|
||||||
"The field by which to sort the results.\n"
|
"The field by which to sort the results.\n"
|
||||||
"Available fields: %s\n"
|
"Available fields: %s\n"
|
||||||
"Default: %%default"
|
"Default: %%default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:200
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:201
|
||||||
msgid "Sort results in ascending order"
|
msgid "Sort results in ascending order"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:202
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:203
|
||||||
msgid "Filter the results by the search query. For the format of the search query, please see the search related documentation in the User Manual. Default is to do no filtering."
|
msgid "Filter the results by the search query. For the format of the search query, please see the search related documentation in the User Manual. Default is to do no filtering."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:204
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:205
|
||||||
msgid "The maximum width of a single line in the output. Defaults to detecting screen size."
|
msgid "The maximum width of a single line in the output. Defaults to detecting screen size."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:205
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:206
|
||||||
msgid "The string used to separate fields. Default is a space."
|
msgid "The string used to separate fields. Default is a space."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:206
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:207
|
||||||
msgid "The prefix for all file paths. Default is the absolute path to the library folder."
|
msgid "The prefix for all file paths. Default is the absolute path to the library folder."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:209
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:210
|
||||||
msgid "The format in which to output the data. Available choices: %s. Defaults is text."
|
msgid "The format in which to output the data. Available choices: %s. Defaults is text."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:217
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:218
|
||||||
msgid "Invalid fields. Available fields:"
|
msgid "Invalid fields. Available fields:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:224
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:225
|
||||||
msgid "Invalid sort field. Available fields:"
|
msgid "Invalid sort field. Available fields:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:295
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:296
|
||||||
msgid "The following books were not added as they already exist in the database (see --duplicates option):"
|
msgid "The following books were not added as they already exist in the database (see --duplicates option):"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:321
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:322
|
||||||
msgid ""
|
msgid ""
|
||||||
"%prog add [options] file1 file2 file3 ...\n"
|
"%prog add [options] file1 file2 file3 ...\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -5771,49 +5771,49 @@ msgid ""
|
|||||||
"the directory related options below.\n"
|
"the directory related options below.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:330
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:331
|
||||||
msgid "Assume that each directory has only a single logical book and that all files in it are different e-book formats of that book"
|
msgid "Assume that each directory has only a single logical book and that all files in it are different e-book formats of that book"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:332
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:333
|
||||||
msgid "Process directories recursively"
|
msgid "Process directories recursively"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:334
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:335
|
||||||
msgid "Add books to database even if they already exist. Comparison is done based on book titles."
|
msgid "Add books to database even if they already exist. Comparison is done based on book titles."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:339
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:340
|
||||||
msgid "You must specify at least one file to add"
|
msgid "You must specify at least one file to add"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:357
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:358
|
||||||
msgid ""
|
msgid ""
|
||||||
"%prog remove ids\n"
|
"%prog remove ids\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Remove the books identified by ids from the database. ids should be a comma separated list of id numbers (you can get id numbers by using the list command). For example, 23,34,57-85\n"
|
"Remove the books identified by ids from the database. ids should be a comma separated list of id numbers (you can get id numbers by using the list command). For example, 23,34,57-85\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:369
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:370
|
||||||
msgid "You must specify at least one book to remove"
|
msgid "You must specify at least one book to remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:389
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:390
|
||||||
msgid ""
|
msgid ""
|
||||||
"%prog add_format [options] id ebook_file\n"
|
"%prog add_format [options] id ebook_file\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Add the ebook in ebook_file to the available formats for the logical book identified by id. You can get id by using the list command. If the format already exists, it is replaced.\n"
|
"Add the ebook in ebook_file to the available formats for the logical book identified by id. You can get id by using the list command. If the format already exists, it is replaced.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:400
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:401
|
||||||
msgid "You must specify an id and an ebook file"
|
msgid "You must specify an id and an ebook file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:405
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:406
|
||||||
msgid "ebook file must have an extension"
|
msgid "ebook file must have an extension"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:413
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:414
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
"%prog remove_format [options] id fmt\n"
|
"%prog remove_format [options] id fmt\n"
|
||||||
@ -5821,11 +5821,11 @@ msgid ""
|
|||||||
"Remove the format fmt from the logical book identified by id. You can get id by using the list command. fmt should be a file extension like LRF or TXT or EPUB. If the logical book does not have fmt available, do nothing.\n"
|
"Remove the format fmt from the logical book identified by id. You can get id by using the list command. fmt should be a file extension like LRF or TXT or EPUB. If the logical book does not have fmt available, do nothing.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:426
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:427
|
||||||
msgid "You must specify an id and a format"
|
msgid "You must specify an id and a format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:444
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:445
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
"%prog show_metadata [options] id\n"
|
"%prog show_metadata [options] id\n"
|
||||||
@ -5834,15 +5834,15 @@ msgid ""
|
|||||||
"id is an id number from the list command.\n"
|
"id is an id number from the list command.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:452
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:453
|
||||||
msgid "Print metadata in OPF form (XML)"
|
msgid "Print metadata in OPF form (XML)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:457
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:458
|
||||||
msgid "You must specify an id"
|
msgid "You must specify an id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:471
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:472
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
"%prog set_metadata [options] id /path/to/metadata.opf\n"
|
"%prog set_metadata [options] id /path/to/metadata.opf\n"
|
||||||
@ -5853,11 +5853,11 @@ msgid ""
|
|||||||
"show_metadata command.\n"
|
"show_metadata command.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:484
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:485
|
||||||
msgid "You must specify an id and a metadata file"
|
msgid "You must specify an id and a metadata file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:496
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:497
|
||||||
msgid ""
|
msgid ""
|
||||||
"%prog export [options] ids\n"
|
"%prog export [options] ids\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -5866,27 +5866,27 @@ msgid ""
|
|||||||
"an opf file). You can get id numbers from the list command.\n"
|
"an opf file). You can get id numbers from the list command.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:504
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:505
|
||||||
msgid "Export all books in database, ignoring the list of ids."
|
msgid "Export all books in database, ignoring the list of ids."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:506
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:507
|
||||||
msgid "Export books to the specified directory. Default is"
|
msgid "Export books to the specified directory. Default is"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:508
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:509
|
||||||
msgid "Export all books into a single directory"
|
msgid "Export all books into a single directory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:510
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:511
|
||||||
msgid "Create file names as author - title instead of title - author"
|
msgid "Create file names as author - title instead of title - author"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:515
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:516
|
||||||
msgid "You must specify some ids or the %s option"
|
msgid "You must specify some ids or the %s option"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/cli.py:525
|
#: /home/kovid/work/calibre/src/calibre/library/cli.py:526
|
||||||
msgid ""
|
msgid ""
|
||||||
"%%prog command [options] [arguments]\n"
|
"%%prog command [options] [arguments]\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -5898,15 +5898,15 @@ msgid ""
|
|||||||
"For help on an individual command: %%prog command --help\n"
|
"For help on an individual command: %%prog command --help\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1539
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1541
|
||||||
msgid "<p>Migrating old database to ebook library in %s<br><center>"
|
msgid "<p>Migrating old database to ebook library in %s<br><center>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1568
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1570
|
||||||
msgid "Copying <b>%s</b>"
|
msgid "Copying <b>%s</b>"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1585
|
#: /home/kovid/work/calibre/src/calibre/library/database2.py:1587
|
||||||
msgid "Compacting database"
|
msgid "Compacting database"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -6257,6 +6257,7 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nspm_int.py:17
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nspm_int.py:17
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes.py:17
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes.py:17
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes_sub.py:17
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_nytimes_sub.py:17
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_ourdailybread.py:16
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_outlook_india.py:17
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_outlook_india.py:17
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_phd_comics.py:16
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_phd_comics.py:16
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_physics_today.py:11
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_physics_today.py:11
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -83,11 +83,12 @@ else:
|
|||||||
if _lib is None:
|
if _lib is None:
|
||||||
_lib = util.find_library('Wand')
|
_lib = util.find_library('Wand')
|
||||||
|
|
||||||
_magick = _magick_error = None
|
_magick = None
|
||||||
|
_magick_error = None
|
||||||
try:
|
try:
|
||||||
_magick = ctypes.CDLL(_lib)
|
_magick = ctypes.CDLL(_lib)
|
||||||
except Exception, err:
|
except Exception, err:
|
||||||
global _magick_error
|
#global _magick_error
|
||||||
_magick_error = str(err)
|
_magick_error = str(err)
|
||||||
|
|
||||||
_initialized = False
|
_initialized = False
|
||||||
|
@ -210,6 +210,12 @@ class BasicNewsRecipe(Recipe):
|
|||||||
#: tags before the first element with `id="content"`.
|
#: tags before the first element with `id="content"`.
|
||||||
remove_tags_before = None
|
remove_tags_before = None
|
||||||
|
|
||||||
|
#: List of attributes to remove from all tags
|
||||||
|
#: For example::
|
||||||
|
#:
|
||||||
|
#: remove_attributes = ['style', 'font']
|
||||||
|
remove_attributes = []
|
||||||
|
|
||||||
#: Keep only the specified tags and their children.
|
#: Keep only the specified tags and their children.
|
||||||
#: For the format for specifying a tag see :attr:`BasicNewsRecipe.remove_tags`.
|
#: For the format for specifying a tag see :attr:`BasicNewsRecipe.remove_tags`.
|
||||||
#: If this list is not empty, then the `<body>` tag will be emptied and re-filled with
|
#: If this list is not empty, then the `<body>` tag will be emptied and re-filled with
|
||||||
@ -562,6 +568,9 @@ class BasicNewsRecipe(Recipe):
|
|||||||
script.extract()
|
script.extract()
|
||||||
for script in list(soup.findAll('noscript')):
|
for script in list(soup.findAll('noscript')):
|
||||||
script.extract()
|
script.extract()
|
||||||
|
for attr in self.remove_attributes:
|
||||||
|
for x in soup.findAll(attrs={attr:True}):
|
||||||
|
del x[attr]
|
||||||
return self.postprocess_html(soup, first_fetch)
|
return self.postprocess_html(soup, first_fetch)
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,14 +11,28 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
|||||||
class TheAtlantic(BasicNewsRecipe):
|
class TheAtlantic(BasicNewsRecipe):
|
||||||
|
|
||||||
title = 'The Atlantic'
|
title = 'The Atlantic'
|
||||||
__author__ = 'Kovid Goyal'
|
__author__ = 'Kovid Goyal and Sujata Raman'
|
||||||
description = 'Current affairs and politics focussed on the US'
|
description = 'Current affairs and politics focussed on the US'
|
||||||
INDEX = 'http://www.theatlantic.com/doc/current'
|
INDEX = 'http://www.theatlantic.com/doc/current'
|
||||||
language = _('English')
|
language = _('English')
|
||||||
remove_tags_before = dict(name='div', id='storytop')
|
remove_tags_before = dict(name='div', id='storytop')
|
||||||
remove_tags = [dict(name='div', id=['seealso', 'storybottom', 'footer', 'ad_banner_top', 'sidebar'])]
|
remove_tags = [
|
||||||
|
dict(name='div', id=['seealso','storybottom', 'footer', 'ad_banner_top', 'sidebar','articletoolstop','subcontent',]),
|
||||||
|
dict(name='p', attrs={'id':["pagination"]}),
|
||||||
|
dict(name='table',attrs={'class':"tools"}),
|
||||||
|
dict(name='a', href='/a/newsletters.mhtml')
|
||||||
|
]
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
|
|
||||||
|
extra_css = '''
|
||||||
|
#timestamp{font-family:Arial,Helvetica,sans-serif; color:#666666 ;font-size:x-small}
|
||||||
|
#storytype{font-family:Arial,Helvetica,sans-serif; color:#D52B1E ;font-weight:bold; font-size:x-small}
|
||||||
|
h2{font-family:georgia,serif; font-style:italic;font-size:x-small;font-weight:normal;}
|
||||||
|
h1{font-family:georgia,serif; font-weight:bold; font-size:large}
|
||||||
|
#byline{font-family:georgia,serif; font-weight:bold; font-size:x-small}
|
||||||
|
#topgraf{font-family:Arial,Helvetica,sans-serif;font-size:x-small;font-weight:bold;}
|
||||||
|
.artsans{{font-family:Arial,Helvetica,sans-serif;font-size:x-small;}
|
||||||
|
'''
|
||||||
def parse_index(self):
|
def parse_index(self):
|
||||||
articles = []
|
articles = []
|
||||||
|
|
||||||
@ -35,13 +49,14 @@ class TheAtlantic(BasicNewsRecipe):
|
|||||||
for item in soup.findAll('div', attrs={'class':'item'}):
|
for item in soup.findAll('div', attrs={'class':'item'}):
|
||||||
a = item.find('a')
|
a = item.find('a')
|
||||||
if a and a.has_key('href'):
|
if a and a.has_key('href'):
|
||||||
url = a['href'].replace('/doc', 'doc/print')
|
url = a['href']#.replace('/doc', 'doc/print')
|
||||||
if not url.startswith('http://'):
|
if not url.startswith('http://'):
|
||||||
url = 'http://www.theatlantic.com/'+url
|
url = 'http://www.theatlantic.com/'+url
|
||||||
title = self.tag_to_string(a)
|
title = self.tag_to_string(a)
|
||||||
byline = item.find(attrs={'class':'byline'})
|
byline = item.find(attrs={'class':'byline'})
|
||||||
date = self.tag_to_string(byline) if byline else ''
|
date = self.tag_to_string(byline) if byline else ''
|
||||||
description = ''
|
description = ''
|
||||||
|
|
||||||
articles.append({
|
articles.append({
|
||||||
'title':title,
|
'title':title,
|
||||||
'date':date,
|
'date':date,
|
||||||
@ -49,4 +64,6 @@ class TheAtlantic(BasicNewsRecipe):
|
|||||||
'description':description
|
'description':description
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return [('Current Issue', articles)]
|
return [('Current Issue', articles)]
|
||||||
|
@ -70,11 +70,11 @@ Usage may be::
|
|||||||
__all__ = ['css', 'stylesheets', 'CSSParser', 'CSSSerializer']
|
__all__ = ['css', 'stylesheets', 'CSSParser', 'CSSSerializer']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__author__ = 'Christof Hoeke with contributions by Walter Doerwald'
|
__author__ = 'Christof Hoeke with contributions by Walter Doerwald'
|
||||||
__date__ = '$LastChangedDate:: 2009-05-09 13:59:54 -0700 #$:'
|
__date__ = '$LastChangedDate:: 2009-08-01 16:10:11 -0600 #$:'
|
||||||
|
|
||||||
VERSION = '0.9.6a5'
|
VERSION = '0.9.6b3'
|
||||||
|
|
||||||
__version__ = '%s $Id: __init__.py 1747 2009-05-09 20:59:54Z cthedot $' % VERSION
|
__version__ = '%s $Id: __init__.py 1832 2009-08-01 22:10:11Z cthedot $' % VERSION
|
||||||
|
|
||||||
import codec
|
import codec
|
||||||
import xml.dom
|
import xml.dom
|
||||||
@ -165,6 +165,23 @@ def parse(*a, **k):
|
|||||||
return parseFile(*a, **k)
|
return parseFile(*a, **k)
|
||||||
parse.__doc__ = CSSParser.parse.__doc__
|
parse.__doc__ = CSSParser.parse.__doc__
|
||||||
|
|
||||||
|
def parseStyle(cssText, encoding='utf-8'):
|
||||||
|
"""Parse given `cssText` which is assumed to be the content of
|
||||||
|
a HTML style attribute.
|
||||||
|
|
||||||
|
:param cssText:
|
||||||
|
CSS string to parse
|
||||||
|
:param encoding:
|
||||||
|
It will be used to decode `cssText` if given as a (byte)
|
||||||
|
string.
|
||||||
|
:returns:
|
||||||
|
:class:`~cssutils.css.CSSStyleDeclaration`
|
||||||
|
"""
|
||||||
|
if isinstance(cssText, str):
|
||||||
|
cssText = cssText.decode(encoding)
|
||||||
|
style = css.CSSStyleDeclaration()
|
||||||
|
style.cssText = cssText
|
||||||
|
return style
|
||||||
|
|
||||||
# set "ser", default serializer
|
# set "ser", default serializer
|
||||||
def setSerializer(serializer):
|
def setSerializer(serializer):
|
||||||
@ -172,7 +189,6 @@ def setSerializer(serializer):
|
|||||||
global ser
|
global ser
|
||||||
ser = serializer
|
ser = serializer
|
||||||
|
|
||||||
|
|
||||||
def getUrls(sheet):
|
def getUrls(sheet):
|
||||||
"""Retrieve all ``url(urlstring)`` values (in e.g.
|
"""Retrieve all ``url(urlstring)`` values (in e.g.
|
||||||
:class:`cssutils.css.CSSImportRule` or :class:`cssutils.css.CSSValue`
|
:class:`cssutils.css.CSSImportRule` or :class:`cssutils.css.CSSValue`
|
||||||
@ -284,5 +300,6 @@ def resolveImports(sheet, target=None):
|
|||||||
target.add(rule)
|
target.add(rule)
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print __doc__
|
print __doc__
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
"""Default URL reading functions"""
|
"""Default URL reading functions"""
|
||||||
__all__ = ['_defaultFetcher', '_readUrl']
|
__all__ = ['_defaultFetcher']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: tokenize2.py 1547 2008-12-10 20:42:26Z cthedot $'
|
__version__ = '$Id: tokenize2.py 1547 2008-12-10 20:42:26Z cthedot $'
|
||||||
|
|
||||||
|
from cssutils import VERSION
|
||||||
import encutils
|
import encutils
|
||||||
import errorhandler
|
import errorhandler
|
||||||
import urllib2
|
import urllib2
|
||||||
@ -16,8 +17,11 @@ def _defaultFetcher(url):
|
|||||||
|
|
||||||
Returns ``(encoding, string)`` or ``None``
|
Returns ``(encoding, string)`` or ``None``
|
||||||
"""
|
"""
|
||||||
|
request = urllib2.Request(url)
|
||||||
|
request.add_header('User-agent',
|
||||||
|
'cssutils %s (http://www.cthedot.de/cssutils/)' % VERSION)
|
||||||
try:
|
try:
|
||||||
res = urllib2.urlopen(url)
|
res = urllib2.urlopen(request)
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
# e.g if file URL and not found
|
# e.g if file URL and not found
|
||||||
log.warn(e, error=OSError)
|
log.warn(e, error=OSError)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""GAE specific URL reading functions"""
|
"""GAE specific URL reading functions"""
|
||||||
__all__ = ['_defaultFetcher', '_readUrl']
|
__all__ = ['_defaultFetcher']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: tokenize2.py 1547 2008-12-10 20:42:26Z cthedot $'
|
__version__ = '$Id: tokenize2.py 1547 2008-12-10 20:42:26Z cthedot $'
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
"""CSSFontFaceRule implements DOM Level 2 CSS CSSFontFaceRule.
|
"""CSSFontFaceRule implements DOM Level 2 CSS CSSFontFaceRule.
|
||||||
|
|
||||||
|
From cssutils 0.9.6 additions from CSS Fonts Module Level 3 are
|
||||||
|
added http://www.w3.org/TR/css3-fonts/.
|
||||||
"""
|
"""
|
||||||
__all__ = ['CSSFontFaceRule']
|
__all__ = ['CSSFontFaceRule']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssfontfacerule.py 1638 2009-01-13 20:39:33Z cthedot $'
|
__version__ = '$Id: cssfontfacerule.py 1818 2009-07-30 21:39:00Z cthedot $'
|
||||||
|
|
||||||
from cssstyledeclaration import CSSStyleDeclaration
|
from cssstyledeclaration import CSSStyleDeclaration
|
||||||
import cssrule
|
import cssrule
|
||||||
@ -21,6 +24,11 @@ class CSSFontFaceRule(cssrule.CSSRule):
|
|||||||
: FONT_FACE_SYM S*
|
: FONT_FACE_SYM S*
|
||||||
'{' S* declaration [ ';' S* declaration ]* '}' S*
|
'{' S* declaration [ ';' S* declaration ]* '}' S*
|
||||||
;
|
;
|
||||||
|
|
||||||
|
cssutils uses a :class:`~cssutils.css.CSSStyleDeclaration` to
|
||||||
|
represent the font descriptions. For validation a specific profile
|
||||||
|
is used though were some properties have other valid values than
|
||||||
|
when used in e.g. a :class:`~cssutils.css.CSSStyleRule`.
|
||||||
"""
|
"""
|
||||||
def __init__(self, style=None, parentRule=None,
|
def __init__(self, style=None, parentRule=None,
|
||||||
parentStyleSheet=None, readonly=False):
|
parentStyleSheet=None, readonly=False):
|
||||||
@ -28,15 +36,15 @@ class CSSFontFaceRule(cssrule.CSSRule):
|
|||||||
If readonly allows setting of properties in constructor only.
|
If readonly allows setting of properties in constructor only.
|
||||||
|
|
||||||
:param style:
|
:param style:
|
||||||
CSSStyleDeclaration for this CSSStyleRule
|
CSSStyleDeclaration used to hold any font descriptions
|
||||||
|
for this CSSFontFaceRule
|
||||||
"""
|
"""
|
||||||
super(CSSFontFaceRule, self).__init__(parentRule=parentRule,
|
super(CSSFontFaceRule, self).__init__(parentRule=parentRule,
|
||||||
parentStyleSheet=parentStyleSheet)
|
parentStyleSheet=parentStyleSheet)
|
||||||
self._atkeyword = u'@font-face'
|
self._atkeyword = u'@font-face'
|
||||||
|
self._style = CSSStyleDeclaration(parentRule=self)
|
||||||
if style:
|
if style:
|
||||||
self.style = style
|
self.style = style
|
||||||
else:
|
|
||||||
self._style = CSSStyleDeclaration(parentRule=self)
|
|
||||||
|
|
||||||
self._readonly = readonly
|
self._readonly = readonly
|
||||||
|
|
||||||
@ -45,8 +53,9 @@ class CSSFontFaceRule(cssrule.CSSRule):
|
|||||||
self.__class__.__name__, self.style.cssText)
|
self.__class__.__name__, self.style.cssText)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "<cssutils.css.%s object style=%r at 0x%x>" % (
|
return "<cssutils.css.%s object style=%r valid=%r at 0x%x>" % (
|
||||||
self.__class__.__name__, self.style.cssText, id(self))
|
self.__class__.__name__, self.style.cssText, self.valid,
|
||||||
|
id(self))
|
||||||
|
|
||||||
def _getCssText(self):
|
def _getCssText(self):
|
||||||
"""Return serialized property cssText."""
|
"""Return serialized property cssText."""
|
||||||
@ -112,15 +121,22 @@ class CSSFontFaceRule(cssrule.CSSRule):
|
|||||||
self._log.error(u'CSSFontFaceRule: Trailing content found.',
|
self._log.error(u'CSSFontFaceRule: Trailing content found.',
|
||||||
token=nonetoken)
|
token=nonetoken)
|
||||||
|
|
||||||
newstyle = CSSStyleDeclaration()
|
teststyle = CSSStyleDeclaration(parentRule=self)
|
||||||
if 'EOF' == typ:
|
if 'EOF' == typ:
|
||||||
# add again as style needs it
|
# add again as style needs it
|
||||||
styletokens.append(braceorEOFtoken)
|
styletokens.append(braceorEOFtoken)
|
||||||
newstyle.cssText = styletokens
|
# may raise:
|
||||||
|
teststyle.cssText = styletokens
|
||||||
|
|
||||||
if wellformed:
|
if wellformed:
|
||||||
self.style = newstyle
|
# contains probably comments only upto {
|
||||||
self._setSeq(newseq) # contains (probably comments) upto { only
|
self._setSeq(newseq)
|
||||||
|
|
||||||
|
# known as correct from before
|
||||||
|
cssutils.log.enabled = False
|
||||||
|
self.style.cssText = styletokens
|
||||||
|
cssutils.log.enabled = True
|
||||||
|
|
||||||
|
|
||||||
cssText = property(_getCssText, _setCssText,
|
cssText = property(_getCssText, _setCssText,
|
||||||
doc="(DOM) The parsable textual representation of this rule.")
|
doc="(DOM) The parsable textual representation of this rule.")
|
||||||
@ -132,9 +148,10 @@ class CSSFontFaceRule(cssrule.CSSRule):
|
|||||||
"""
|
"""
|
||||||
self._checkReadonly()
|
self._checkReadonly()
|
||||||
if isinstance(style, basestring):
|
if isinstance(style, basestring):
|
||||||
self._style = CSSStyleDeclaration(parentRule=self, cssText=style)
|
self._style.cssText = style
|
||||||
else:
|
else:
|
||||||
self._style._seq = style.seq
|
self._style = style
|
||||||
|
self._style.parentRule = self
|
||||||
|
|
||||||
style = property(lambda self: self._style, _setStyle,
|
style = property(lambda self: self._style, _setStyle,
|
||||||
doc="(DOM) The declaration-block of this rule set, "
|
doc="(DOM) The declaration-block of this rule set, "
|
||||||
@ -144,5 +161,20 @@ class CSSFontFaceRule(cssrule.CSSRule):
|
|||||||
doc="The type of this rule, as defined by a CSSRule "
|
doc="The type of this rule, as defined by a CSSRule "
|
||||||
"type constant.")
|
"type constant.")
|
||||||
|
|
||||||
|
def _getValid(self):
|
||||||
|
needed = ['font-family', 'src']
|
||||||
|
for p in self.style.getProperties(all=True):
|
||||||
|
if not p.valid:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
needed.remove(p.name)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
return not bool(needed)
|
||||||
|
|
||||||
|
valid = property(_getValid, doc='CSSFontFace is valid if properties '
|
||||||
|
'`font-family` and `src` are set and all properties are '
|
||||||
|
'valid.')
|
||||||
|
|
||||||
# constant but needed:
|
# constant but needed:
|
||||||
wellformed = property(lambda self: True)
|
wellformed = property(lambda self: True)
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
"""CSSImportRule implements DOM Level 2 CSS CSSImportRule plus the
|
"""CSSImportRule implements DOM Level 2 CSS CSSImportRule plus the
|
||||||
``name`` property from http://www.w3.org/TR/css3-cascade/#cascading.
|
``name`` property from http://www.w3.org/TR/css3-cascade/#cascading."""
|
||||||
|
|
||||||
"""
|
|
||||||
__all__ = ['CSSImportRule']
|
__all__ = ['CSSImportRule']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssimportrule.py 1638 2009-01-13 20:39:33Z cthedot $'
|
__version__ = '$Id: cssimportrule.py 1824 2009-08-01 21:00:34Z cthedot $'
|
||||||
|
|
||||||
import cssrule
|
import cssrule
|
||||||
import cssutils
|
import cssutils
|
||||||
@ -320,7 +318,8 @@ class CSSImportRule(cssrule.CSSRule):
|
|||||||
parentHref = self.parentStyleSheet.href
|
parentHref = self.parentStyleSheet.href
|
||||||
if parentHref is None:
|
if parentHref is None:
|
||||||
# use cwd instead
|
# use cwd instead
|
||||||
parentHref = u'file:' + urllib.pathname2url(os.getcwd()) + '/'
|
#parentHref = u'file:' + urllib.pathname2url(os.getcwd()) + '/'
|
||||||
|
parentHref = cssutils.helper.path2url(os.getcwd()) + '/'
|
||||||
href = urlparse.urljoin(parentHref, self.href)
|
href = urlparse.urljoin(parentHref, self.href)
|
||||||
|
|
||||||
# all possible exceptions are ignored (styleSheet is None then)
|
# all possible exceptions are ignored (styleSheet is None then)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""CSSMediaRule implements DOM Level 2 CSS CSSMediaRule."""
|
"""CSSMediaRule implements DOM Level 2 CSS CSSMediaRule."""
|
||||||
__all__ = ['CSSMediaRule']
|
__all__ = ['CSSMediaRule']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssmediarule.py 1743 2009-05-09 20:33:15Z cthedot $'
|
__version__ = '$Id: cssmediarule.py 1820 2009-08-01 20:53:08Z cthedot $'
|
||||||
|
|
||||||
import cssrule
|
import cssrule
|
||||||
import cssutils
|
import cssutils
|
||||||
@ -34,15 +34,11 @@ class CSSMediaRule(cssrule.CSSRule):
|
|||||||
readonly=readonly)
|
readonly=readonly)
|
||||||
self.name = name
|
self.name = name
|
||||||
self.cssRules = cssutils.css.cssrulelist.CSSRuleList()
|
self.cssRules = cssutils.css.cssrulelist.CSSRuleList()
|
||||||
self.cssRules.append = self.insertRule
|
|
||||||
self.cssRules.extend = self.insertRule
|
|
||||||
self.cssRules.__delitem__ == self.deleteRule
|
|
||||||
|
|
||||||
self._readonly = readonly
|
self._readonly = readonly
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""Generator iterating over these rule's cssRules."""
|
"""Generator iterating over these rule's cssRules."""
|
||||||
for rule in self.cssRules:
|
for rule in self._cssRules:
|
||||||
yield rule
|
yield rule
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -53,6 +49,20 @@ class CSSMediaRule(cssrule.CSSRule):
|
|||||||
return "<cssutils.css.%s object mediaText=%r at 0x%x>" % (
|
return "<cssutils.css.%s object mediaText=%r at 0x%x>" % (
|
||||||
self.__class__.__name__, self.media.mediaText, id(self))
|
self.__class__.__name__, self.media.mediaText, id(self))
|
||||||
|
|
||||||
|
def _setCssRules(self, cssRules):
|
||||||
|
"Set new cssRules and update contained rules refs."
|
||||||
|
cssRules.append = self.insertRule
|
||||||
|
cssRules.extend = self.insertRule
|
||||||
|
cssRules.__delitem__ == self.deleteRule
|
||||||
|
for rule in cssRules:
|
||||||
|
rule._parentStyleSheet = self.parentStyleSheet
|
||||||
|
rule._parentRule = self
|
||||||
|
self._cssRules = cssRules
|
||||||
|
|
||||||
|
cssRules = property(lambda self: self._cssRules, _setCssRules,
|
||||||
|
"All Rules in this style sheet, a "
|
||||||
|
":class:`~cssutils.css.CSSRuleList`.")
|
||||||
|
|
||||||
def _getCssText(self):
|
def _getCssText(self):
|
||||||
"""Return serialized property cssText."""
|
"""Return serialized property cssText."""
|
||||||
return cssutils.ser.do_CSSMediaRule(self)
|
return cssutils.ser.do_CSSMediaRule(self)
|
||||||
@ -204,9 +214,9 @@ class CSSMediaRule(cssrule.CSSRule):
|
|||||||
self._media.mediaText = newmedia.mediaText
|
self._media.mediaText = newmedia.mediaText
|
||||||
self.name = name
|
self.name = name
|
||||||
self._setSeq(nameseq)
|
self._setSeq(nameseq)
|
||||||
del self.cssRules[:]
|
del self._cssRules[:]
|
||||||
for r in newcssrules:
|
for r in newcssrules:
|
||||||
self.cssRules.append(r)
|
self._cssRules.append(r)
|
||||||
|
|
||||||
cssText = property(_getCssText, _setCssText,
|
cssText = property(_getCssText, _setCssText,
|
||||||
doc="(DOM) The parsable textual representation of this rule.")
|
doc="(DOM) The parsable textual representation of this rule.")
|
||||||
@ -245,12 +255,12 @@ class CSSMediaRule(cssrule.CSSRule):
|
|||||||
self._checkReadonly()
|
self._checkReadonly()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.cssRules[index]._parentRule = None # detach
|
self._cssRules[index]._parentRule = None # detach
|
||||||
del self.cssRules[index] # remove from @media
|
del self._cssRules[index] # remove from @media
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise xml.dom.IndexSizeErr(
|
raise xml.dom.IndexSizeErr(
|
||||||
u'CSSMediaRule: %s is not a valid index in the rulelist of length %i' % (
|
u'CSSMediaRule: %s is not a valid index in the rulelist of length %i' % (
|
||||||
index, self.cssRules.length))
|
index, self._cssRules.length))
|
||||||
|
|
||||||
def add(self, rule):
|
def add(self, rule):
|
||||||
"""Add `rule` to end of this mediarule.
|
"""Add `rule` to end of this mediarule.
|
||||||
@ -300,11 +310,11 @@ class CSSMediaRule(cssrule.CSSRule):
|
|||||||
|
|
||||||
# check position
|
# check position
|
||||||
if index is None:
|
if index is None:
|
||||||
index = len(self.cssRules)
|
index = len(self._cssRules)
|
||||||
elif index < 0 or index > self.cssRules.length:
|
elif index < 0 or index > self._cssRules.length:
|
||||||
raise xml.dom.IndexSizeErr(
|
raise xml.dom.IndexSizeErr(
|
||||||
u'CSSMediaRule: Invalid index %s for CSSRuleList with a length of %s.' % (
|
u'CSSMediaRule: Invalid index %s for CSSRuleList with a length of %s.' % (
|
||||||
index, self.cssRules.length))
|
index, self._cssRules.length))
|
||||||
|
|
||||||
# parse
|
# parse
|
||||||
if isinstance(rule, basestring):
|
if isinstance(rule, basestring):
|
||||||
@ -315,6 +325,13 @@ class CSSMediaRule(cssrule.CSSRule):
|
|||||||
self._log.error(u'CSSMediaRule: Invalid Rule: %s' % rule)
|
self._log.error(u'CSSMediaRule: Invalid Rule: %s' % rule)
|
||||||
return
|
return
|
||||||
rule = tempsheet.cssRules[0]
|
rule = tempsheet.cssRules[0]
|
||||||
|
|
||||||
|
elif isinstance(rule, cssutils.css.CSSRuleList):
|
||||||
|
# insert all rules
|
||||||
|
for i, r in enumerate(rule):
|
||||||
|
self.insertRule(r, index + i)
|
||||||
|
return index
|
||||||
|
|
||||||
elif not isinstance(rule, cssutils.css.CSSRule):
|
elif not isinstance(rule, cssutils.css.CSSRule):
|
||||||
self._log.error(u'CSSMediaRule: Not a CSSRule: %s' % rule)
|
self._log.error(u'CSSMediaRule: Not a CSSRule: %s' % rule)
|
||||||
return
|
return
|
||||||
@ -332,7 +349,7 @@ class CSSMediaRule(cssrule.CSSRule):
|
|||||||
error=xml.dom.HierarchyRequestErr)
|
error=xml.dom.HierarchyRequestErr)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.cssRules.insert(index, rule)
|
self._cssRules.insert(index, rule)
|
||||||
rule._parentRule = self
|
rule._parentRule = self
|
||||||
rule._parentStyleSheet = self.parentStyleSheet
|
rule._parentStyleSheet = self.parentStyleSheet
|
||||||
return index
|
return index
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
"""CSSPageRule implements DOM Level 2 CSS CSSPageRule.
|
"""CSSPageRule implements DOM Level 2 CSS CSSPageRule."""
|
||||||
"""
|
|
||||||
__all__ = ['CSSPageRule']
|
__all__ = ['CSSPageRule']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: csspagerule.py 1658 2009-02-07 18:24:40Z cthedot $'
|
__version__ = '$Id: csspagerule.py 1824 2009-08-01 21:00:34Z cthedot $'
|
||||||
|
|
||||||
from cssstyledeclaration import CSSStyleDeclaration
|
from cssstyledeclaration import CSSStyleDeclaration
|
||||||
from selectorlist import SelectorList
|
from selectorlist import SelectorList
|
||||||
@ -45,11 +44,12 @@ class CSSPageRule(cssrule.CSSRule):
|
|||||||
tempseq.append(self.selectorText, 'selectorText')
|
tempseq.append(self.selectorText, 'selectorText')
|
||||||
else:
|
else:
|
||||||
self._selectorText = self._tempSeq()
|
self._selectorText = self._tempSeq()
|
||||||
|
|
||||||
|
self._style = CSSStyleDeclaration(parentRule=self)
|
||||||
if style:
|
if style:
|
||||||
self.style = style
|
self.style = style
|
||||||
tempseq.append(self.style, 'style')
|
tempseq.append(self.style, 'style')
|
||||||
else:
|
|
||||||
self._style = CSSStyleDeclaration(parentRule=self)
|
|
||||||
self._setSeq(tempseq)
|
self._setSeq(tempseq)
|
||||||
|
|
||||||
self._readonly = readonly
|
self._readonly = readonly
|
||||||
@ -192,7 +192,7 @@ class CSSPageRule(cssrule.CSSRule):
|
|||||||
|
|
||||||
wellformed, newselectorseq = self.__parseSelectorText(selectortokens)
|
wellformed, newselectorseq = self.__parseSelectorText(selectortokens)
|
||||||
|
|
||||||
newstyle = CSSStyleDeclaration()
|
teststyle = CSSStyleDeclaration(parentRule=self)
|
||||||
val, typ = self._tokenvalue(braceorEOFtoken), self._type(braceorEOFtoken)
|
val, typ = self._tokenvalue(braceorEOFtoken), self._type(braceorEOFtoken)
|
||||||
if val != u'}' and typ != 'EOF':
|
if val != u'}' and typ != 'EOF':
|
||||||
wellformed = False
|
wellformed = False
|
||||||
@ -203,12 +203,14 @@ class CSSPageRule(cssrule.CSSRule):
|
|||||||
if 'EOF' == typ:
|
if 'EOF' == typ:
|
||||||
# add again as style needs it
|
# add again as style needs it
|
||||||
styletokens.append(braceorEOFtoken)
|
styletokens.append(braceorEOFtoken)
|
||||||
newstyle.cssText = styletokens
|
teststyle.cssText = styletokens
|
||||||
|
|
||||||
if wellformed:
|
if wellformed:
|
||||||
self._selectorText = newselectorseq # already parsed
|
# known as correct from before
|
||||||
self.style = newstyle
|
cssutils.log.enabled = False
|
||||||
self._setSeq(newselectorseq) # contains upto style only
|
self._selectorText = newselectorseq # TODO: TEST and REFS
|
||||||
|
self.style.cssText = styletokens
|
||||||
|
cssutils.log.enabled = True
|
||||||
|
|
||||||
cssText = property(_getCssText, _setCssText,
|
cssText = property(_getCssText, _setCssText,
|
||||||
doc="(DOM) The parsable textual representation of this rule.")
|
doc="(DOM) The parsable textual representation of this rule.")
|
||||||
@ -239,7 +241,7 @@ class CSSPageRule(cssrule.CSSRule):
|
|||||||
|
|
||||||
# may raise SYNTAX_ERR
|
# may raise SYNTAX_ERR
|
||||||
wellformed, newseq = self.__parseSelectorText(selectorText)
|
wellformed, newseq = self.__parseSelectorText(selectorText)
|
||||||
if wellformed and newseq:
|
if wellformed:
|
||||||
self._selectorText = newseq
|
self._selectorText = newseq
|
||||||
|
|
||||||
selectorText = property(_getSelectorText, _setSelectorText,
|
selectorText = property(_getSelectorText, _setSelectorText,
|
||||||
@ -251,19 +253,16 @@ class CSSPageRule(cssrule.CSSRule):
|
|||||||
a CSSStyleDeclaration or string
|
a CSSStyleDeclaration or string
|
||||||
"""
|
"""
|
||||||
self._checkReadonly()
|
self._checkReadonly()
|
||||||
|
|
||||||
if isinstance(style, basestring):
|
if isinstance(style, basestring):
|
||||||
self._style.cssText = style
|
self._style.cssText = style
|
||||||
else:
|
else:
|
||||||
# cssText would be serialized with optional preferences
|
self._style = style
|
||||||
# so use seq!
|
self._style.parentRule = self
|
||||||
self._style._seq = style.seq
|
|
||||||
|
|
||||||
style = property(lambda self: self._style, _setStyle,
|
style = property(lambda self: self._style, _setStyle,
|
||||||
doc="(DOM) The declaration-block of this rule set, "
|
doc="(DOM) The declaration-block of this rule set, "
|
||||||
"a :class:`~cssutils.css.CSSStyleDeclaration`.")
|
"a :class:`~cssutils.css.CSSStyleDeclaration`.")
|
||||||
|
|
||||||
|
|
||||||
type = property(lambda self: self.PAGE_RULE,
|
type = property(lambda self: self.PAGE_RULE,
|
||||||
doc="The type of this rule, as defined by a CSSRule "
|
doc="The type of this rule, as defined by a CSSRule "
|
||||||
"type constant.")
|
"type constant.")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""CSSRule implements DOM Level 2 CSS CSSRule."""
|
"""CSSRule implements DOM Level 2 CSS CSSRule."""
|
||||||
__all__ = ['CSSRule']
|
__all__ = ['CSSRule']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssrule.py 1638 2009-01-13 20:39:33Z cthedot $'
|
__version__ = '$Id: cssrule.py 1808 2009-07-29 13:09:36Z cthedot $'
|
||||||
|
|
||||||
import cssutils
|
import cssutils
|
||||||
import xml.dom
|
import xml.dom
|
||||||
@ -35,6 +35,7 @@ class CSSRule(cssutils.util.Base2):
|
|||||||
def __init__(self, parentRule=None, parentStyleSheet=None, readonly=False):
|
def __init__(self, parentRule=None, parentStyleSheet=None, readonly=False):
|
||||||
"""Set common attributes for all rules."""
|
"""Set common attributes for all rules."""
|
||||||
super(CSSRule, self).__init__()
|
super(CSSRule, self).__init__()
|
||||||
|
self._parent = parentRule
|
||||||
self._parentRule = parentRule
|
self._parentRule = parentRule
|
||||||
self._parentStyleSheet = parentStyleSheet
|
self._parentStyleSheet = parentStyleSheet
|
||||||
self._setSeq(self._tempSeq())
|
self._setSeq(self._tempSeq())
|
||||||
@ -78,6 +79,10 @@ class CSSRule(cssutils.util.Base2):
|
|||||||
"rule. This reflects the current state of the rule "
|
"rule. This reflects the current state of the rule "
|
||||||
"and not its initial value.")
|
"and not its initial value.")
|
||||||
|
|
||||||
|
parent = property(lambda self: self._parent,
|
||||||
|
doc="The Parent Node of this CSSRule (currently if a "
|
||||||
|
"CSSStyleDeclaration only!) or None.")
|
||||||
|
|
||||||
parentRule = property(lambda self: self._parentRule,
|
parentRule = property(lambda self: self._parentRule,
|
||||||
doc="If this rule is contained inside "
|
doc="If this rule is contained inside "
|
||||||
"another rule (e.g. a style rule inside "
|
"another rule (e.g. a style rule inside "
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
"""CSSRuleList implements DOM Level 2 CSS CSSRuleList.
|
"""CSSRuleList implements DOM Level 2 CSS CSSRuleList.
|
||||||
Partly also http://dev.w3.org/csswg/cssom/#the-cssrulelist
|
Partly also http://dev.w3.org/csswg/cssom/#the-cssrulelist."""
|
||||||
"""
|
|
||||||
__all__ = ['CSSRuleList']
|
__all__ = ['CSSRuleList']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssrulelist.py 1641 2009-01-13 21:05:37Z cthedot $'
|
__version__ = '$Id: cssrulelist.py 1824 2009-08-01 21:00:34Z cthedot $'
|
||||||
|
|
||||||
class CSSRuleList(list):
|
class CSSRuleList(list):
|
||||||
"""The CSSRuleList object represents an (ordered) list of statements.
|
"""The CSSRuleList object represents an (ordered) list of statements.
|
||||||
|
@ -51,7 +51,7 @@ TODO:
|
|||||||
"""
|
"""
|
||||||
__all__ = ['CSSStyleDeclaration', 'Property']
|
__all__ = ['CSSStyleDeclaration', 'Property']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssstyledeclaration.py 1710 2009-04-18 15:46:20Z cthedot $'
|
__version__ = '$Id: cssstyledeclaration.py 1819 2009-08-01 20:52:43Z cthedot $'
|
||||||
|
|
||||||
from cssproperties import CSS2Properties
|
from cssproperties import CSS2Properties
|
||||||
from property import Property
|
from property import Property
|
||||||
@ -128,6 +128,11 @@ class CSSStyleDeclaration(CSS2Properties, cssutils.util.Base2):
|
|||||||
yield self.getProperty(name)
|
yield self.getProperty(name)
|
||||||
return properties()
|
return properties()
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
"""Analoguous to standard dict returns property names which are set in
|
||||||
|
this declaration."""
|
||||||
|
return list(self.__nnames())
|
||||||
|
|
||||||
def __getitem__(self, CSSName):
|
def __getitem__(self, CSSName):
|
||||||
"""Retrieve the value of property ``CSSName`` from this declaration.
|
"""Retrieve the value of property ``CSSName`` from this declaration.
|
||||||
|
|
||||||
@ -247,6 +252,13 @@ class CSSStyleDeclaration(CSS2Properties, cssutils.util.Base2):
|
|||||||
"""
|
"""
|
||||||
self.removeProperty(CSSName)
|
self.removeProperty(CSSName)
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
"""Generator yielding any known child in this declaration including
|
||||||
|
*all* properties, comments or CSSUnknownrules.
|
||||||
|
"""
|
||||||
|
for item in self._seq:
|
||||||
|
yield item.value
|
||||||
|
|
||||||
def _getCssText(self):
|
def _getCssText(self):
|
||||||
"""Return serialized property cssText."""
|
"""Return serialized property cssText."""
|
||||||
return cssutils.ser.do_css_CSSStyleDeclaration(self)
|
return cssutils.ser.do_css_CSSStyleDeclaration(self)
|
||||||
@ -275,7 +287,7 @@ class CSSStyleDeclaration(CSS2Properties, cssutils.util.Base2):
|
|||||||
semicolon=True)
|
semicolon=True)
|
||||||
if self._tokenvalue(tokens[-1]) == u';':
|
if self._tokenvalue(tokens[-1]) == u';':
|
||||||
tokens.pop()
|
tokens.pop()
|
||||||
property = Property()
|
property = Property(parent=self)
|
||||||
property.cssText = tokens
|
property.cssText = tokens
|
||||||
if property.wellformed:
|
if property.wellformed:
|
||||||
seq.append(property, 'Property')
|
seq.append(property, 'Property')
|
||||||
@ -301,10 +313,11 @@ class CSSStyleDeclaration(CSS2Properties, cssutils.util.Base2):
|
|||||||
productions={'IDENT': ident},#, 'CHAR': char},
|
productions={'IDENT': ident},#, 'CHAR': char},
|
||||||
default=unexpected)
|
default=unexpected)
|
||||||
# wellformed set by parse
|
# wellformed set by parse
|
||||||
# post conditions
|
|
||||||
|
for item in newseq:
|
||||||
|
item.value._parent = self
|
||||||
|
|
||||||
# do not check wellformed as invalid things are removed anyway
|
# do not check wellformed as invalid things are removed anyway
|
||||||
#if wellformed:
|
|
||||||
self._setSeq(newseq)
|
self._setSeq(newseq)
|
||||||
|
|
||||||
cssText = property(_getCssText, _setCssText,
|
cssText = property(_getCssText, _setCssText,
|
||||||
@ -322,13 +335,12 @@ class CSSStyleDeclaration(CSS2Properties, cssutils.util.Base2):
|
|||||||
"""
|
"""
|
||||||
return cssutils.ser.do_css_CSSStyleDeclaration(self, separator)
|
return cssutils.ser.do_css_CSSStyleDeclaration(self, separator)
|
||||||
|
|
||||||
def _getParentRule(self):
|
|
||||||
return self._parentRule
|
|
||||||
|
|
||||||
def _setParentRule(self, parentRule):
|
def _setParentRule(self, parentRule):
|
||||||
self._parentRule = parentRule
|
self._parentRule = parentRule
|
||||||
|
for x in self.children():
|
||||||
|
x.parent = self
|
||||||
|
|
||||||
parentRule = property(_getParentRule, _setParentRule,
|
parentRule = property(lambda self: self._parentRule, _setParentRule,
|
||||||
doc="(DOM) The CSS rule that contains this declaration block or "
|
doc="(DOM) The CSS rule that contains this declaration block or "
|
||||||
"None if this CSSStyleDeclaration is not attached to a CSSRule.")
|
"None if this CSSStyleDeclaration is not attached to a CSSRule.")
|
||||||
|
|
||||||
@ -581,6 +593,7 @@ class CSSStyleDeclaration(CSS2Properties, cssutils.util.Base2):
|
|||||||
property.priority = newp.priority
|
property.priority = newp.priority
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
newp.parent = self
|
||||||
self.seq._readonly = False
|
self.seq._readonly = False
|
||||||
self.seq.append(newp, 'Property')
|
self.seq.append(newp, 'Property')
|
||||||
self.seq._readonly = True
|
self.seq._readonly = True
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""CSSStyleRule implements DOM Level 2 CSS CSSStyleRule."""
|
"""CSSStyleRule implements DOM Level 2 CSS CSSStyleRule."""
|
||||||
__all__ = ['CSSStyleRule']
|
__all__ = ['CSSStyleRule']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssstylerule.py 1638 2009-01-13 20:39:33Z cthedot $'
|
__version__ = '$Id: cssstylerule.py 1815 2009-07-29 16:51:58Z cthedot $'
|
||||||
|
|
||||||
from cssstyledeclaration import CSSStyleDeclaration
|
from cssstyledeclaration import CSSStyleDeclaration
|
||||||
from selectorlist import SelectorList
|
from selectorlist import SelectorList
|
||||||
@ -107,6 +107,8 @@ class CSSStyleRule(cssrule.CSSRule):
|
|||||||
else:
|
else:
|
||||||
wellformed = True
|
wellformed = True
|
||||||
|
|
||||||
|
testselectorlist, teststyle = None, None
|
||||||
|
|
||||||
bracetoken = selectortokens.pop()
|
bracetoken = selectortokens.pop()
|
||||||
if self._tokenvalue(bracetoken) != u'{':
|
if self._tokenvalue(bracetoken) != u'{':
|
||||||
wellformed = False
|
wellformed = False
|
||||||
@ -117,11 +119,11 @@ class CSSStyleRule(cssrule.CSSRule):
|
|||||||
wellformed = False
|
wellformed = False
|
||||||
self._log.error(u'CSSStyleRule: No selector found: %r.' %
|
self._log.error(u'CSSStyleRule: No selector found: %r.' %
|
||||||
self._valuestr(cssText), bracetoken)
|
self._valuestr(cssText), bracetoken)
|
||||||
newselectorlist = SelectorList(selectorText=(selectortokens,
|
|
||||||
|
testselectorlist = SelectorList(selectorText=(selectortokens,
|
||||||
namespaces),
|
namespaces),
|
||||||
parentRule=self)
|
parentRule=self)
|
||||||
|
|
||||||
newstyle = CSSStyleDeclaration()
|
|
||||||
if not styletokens:
|
if not styletokens:
|
||||||
wellformed = False
|
wellformed = False
|
||||||
self._log.error(
|
self._log.error(
|
||||||
@ -139,11 +141,14 @@ class CSSStyleRule(cssrule.CSSRule):
|
|||||||
if 'EOF' == typ:
|
if 'EOF' == typ:
|
||||||
# add again as style needs it
|
# add again as style needs it
|
||||||
styletokens.append(braceorEOFtoken)
|
styletokens.append(braceorEOFtoken)
|
||||||
newstyle.cssText = styletokens
|
teststyle = CSSStyleDeclaration(styletokens, parentRule=self)
|
||||||
|
|
||||||
if wellformed:
|
if wellformed and testselectorlist and teststyle:
|
||||||
self._selectorList = newselectorlist
|
# known as correct from before
|
||||||
self.style = newstyle
|
cssutils.log.enabled = False
|
||||||
|
self.style.cssText = styletokens
|
||||||
|
self.selectorList.selectorText=(selectortokens, namespaces)
|
||||||
|
cssutils.log.enabled = True
|
||||||
|
|
||||||
cssText = property(_getCssText, _setCssText,
|
cssText = property(_getCssText, _setCssText,
|
||||||
doc="(DOM) The parsable textual representation of this rule.")
|
doc="(DOM) The parsable textual representation of this rule.")
|
||||||
@ -164,11 +169,12 @@ class CSSStyleRule(cssrule.CSSRule):
|
|||||||
|
|
||||||
def _setSelectorList(self, selectorList):
|
def _setSelectorList(self, selectorList):
|
||||||
"""
|
"""
|
||||||
:param selectorList: selectorList, only content is used, not the actual
|
:param selectorList: A SelectorList which replaces the current
|
||||||
object
|
selectorList object
|
||||||
"""
|
"""
|
||||||
self._checkReadonly()
|
self._checkReadonly()
|
||||||
self.selectorText = selectorList.selectorText
|
selectorList._parentRule = self
|
||||||
|
self._selectorList = selectorList
|
||||||
|
|
||||||
selectorList = property(lambda self: self._selectorList, _setSelectorList,
|
selectorList = property(lambda self: self._selectorList, _setSelectorList,
|
||||||
doc="The SelectorList of this rule.")
|
doc="The SelectorList of this rule.")
|
||||||
@ -200,16 +206,15 @@ class CSSStyleRule(cssrule.CSSRule):
|
|||||||
|
|
||||||
def _setStyle(self, style):
|
def _setStyle(self, style):
|
||||||
"""
|
"""
|
||||||
:param style: CSSStyleDeclaration or string, only the cssText of a
|
:param style: A string or CSSStyleDeclaration which replaces the
|
||||||
declaration is used, not the actual object
|
current style object.
|
||||||
"""
|
"""
|
||||||
self._checkReadonly()
|
self._checkReadonly()
|
||||||
if isinstance(style, basestring):
|
if isinstance(style, basestring):
|
||||||
self._style.cssText = style
|
self._style.cssText = style
|
||||||
else:
|
else:
|
||||||
# cssText would be serialized with optional preferences
|
style._parentRule = self
|
||||||
# so use _seq!
|
self._style = style
|
||||||
self._style._seq = style._seq
|
|
||||||
|
|
||||||
style = property(lambda self: self._style, _setStyle,
|
style = property(lambda self: self._style, _setStyle,
|
||||||
doc="(DOM) The declaration-block of this rule set.")
|
doc="(DOM) The declaration-block of this rule set.")
|
||||||
|
@ -9,7 +9,7 @@ TODO:
|
|||||||
"""
|
"""
|
||||||
__all__ = ['CSSStyleSheet']
|
__all__ = ['CSSStyleSheet']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssstylesheet.py 1641 2009-01-13 21:05:37Z cthedot $'
|
__version__ = '$Id: cssstylesheet.py 1820 2009-08-01 20:53:08Z cthedot $'
|
||||||
|
|
||||||
from cssutils.helper import Deprecated
|
from cssutils.helper import Deprecated
|
||||||
from cssutils.util import _Namespaces, _SimpleNamespaces, _readUrl
|
from cssutils.util import _Namespaces, _SimpleNamespaces, _readUrl
|
||||||
@ -42,8 +42,6 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
|
|
||||||
self._ownerRule = ownerRule
|
self._ownerRule = ownerRule
|
||||||
self.cssRules = cssutils.css.CSSRuleList()
|
self.cssRules = cssutils.css.CSSRuleList()
|
||||||
self.cssRules.append = self.insertRule
|
|
||||||
self.cssRules.extend = self.insertRule
|
|
||||||
self._namespaces = _Namespaces(parentStyleSheet=self, log=self._log)
|
self._namespaces = _Namespaces(parentStyleSheet=self, log=self._log)
|
||||||
self._readonly = readonly
|
self._readonly = readonly
|
||||||
|
|
||||||
@ -53,7 +51,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"Generator which iterates over cssRules."
|
"Generator which iterates over cssRules."
|
||||||
for rule in self.cssRules:
|
for rule in self._cssRules:
|
||||||
yield rule
|
yield rule
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -78,7 +76,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
|
|
||||||
def _cleanNamespaces(self):
|
def _cleanNamespaces(self):
|
||||||
"Remove all namespace rules with same namespaceURI but last one set."
|
"Remove all namespace rules with same namespaceURI but last one set."
|
||||||
rules = self.cssRules
|
rules = self._cssRules
|
||||||
namespaceitems = self.namespaces.items()
|
namespaceitems = self.namespaces.items()
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(rules):
|
while i < len(rules):
|
||||||
@ -101,6 +99,19 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
useduris.update(r2.selectorList._getUsedUris())
|
useduris.update(r2.selectorList._getUsedUris())
|
||||||
return useduris
|
return useduris
|
||||||
|
|
||||||
|
def _setCssRules(self, cssRules):
|
||||||
|
"Set new cssRules and update contained rules refs."
|
||||||
|
cssRules.append = self.insertRule
|
||||||
|
cssRules.extend = self.insertRule
|
||||||
|
cssRules.__delitem__ == self.deleteRule
|
||||||
|
for rule in cssRules:
|
||||||
|
rule._parentStyleSheet = self
|
||||||
|
self._cssRules = cssRules
|
||||||
|
|
||||||
|
cssRules = property(lambda self: self._cssRules, _setCssRules,
|
||||||
|
"All Rules in this style sheet, a "
|
||||||
|
":class:`~cssutils.css.CSSRuleList`.")
|
||||||
|
|
||||||
def _getCssText(self):
|
def _getCssText(self):
|
||||||
"Textual representation of the stylesheet (a byte string)."
|
"Textual representation of the stylesheet (a byte string)."
|
||||||
return cssutils.ser.do_CSSStyleSheet(self)
|
return cssutils.ser.do_CSSStyleSheet(self)
|
||||||
@ -260,7 +271,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
default=ruleset)
|
default=ruleset)
|
||||||
|
|
||||||
if wellformed:
|
if wellformed:
|
||||||
del self.cssRules[:]
|
del self._cssRules[:]
|
||||||
for rule in newseq:
|
for rule in newseq:
|
||||||
self.insertRule(rule, _clean=False)
|
self.insertRule(rule, _clean=False)
|
||||||
self._cleanNamespaces()
|
self._cleanNamespaces()
|
||||||
@ -277,7 +288,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
try:
|
try:
|
||||||
# explicit @charset
|
# explicit @charset
|
||||||
selfAsParentEncoding = self.cssRules[0].encoding
|
selfAsParentEncoding = self._cssRules[0].encoding
|
||||||
except (IndexError, AttributeError):
|
except (IndexError, AttributeError):
|
||||||
# default not UTF-8 but None!
|
# default not UTF-8 but None!
|
||||||
selfAsParentEncoding = None
|
selfAsParentEncoding = None
|
||||||
@ -312,6 +323,14 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
"""Set @import URL loader, if None the default is used."""
|
"""Set @import URL loader, if None the default is used."""
|
||||||
self._fetcher = fetcher
|
self._fetcher = fetcher
|
||||||
|
|
||||||
|
def _getEncoding(self):
|
||||||
|
"""Encoding set in :class:`~cssutils.css.CSSCharsetRule` or if ``None``
|
||||||
|
resulting in default ``utf-8`` encoding being used."""
|
||||||
|
try:
|
||||||
|
return self._cssRules[0].encoding
|
||||||
|
except (IndexError, AttributeError):
|
||||||
|
return 'utf-8'
|
||||||
|
|
||||||
def _setEncoding(self, encoding):
|
def _setEncoding(self, encoding):
|
||||||
"""Set `encoding` of charset rule if present in sheet or insert a new
|
"""Set `encoding` of charset rule if present in sheet or insert a new
|
||||||
:class:`~cssutils.css.CSSCharsetRule` with given `encoding`.
|
:class:`~cssutils.css.CSSCharsetRule` with given `encoding`.
|
||||||
@ -319,7 +338,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
default encoding of utf-8.
|
default encoding of utf-8.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
rule = self.cssRules[0]
|
rule = self._cssRules[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
rule = None
|
rule = None
|
||||||
if rule and rule.CHARSET_RULE == rule.type:
|
if rule and rule.CHARSET_RULE == rule.type:
|
||||||
@ -330,14 +349,6 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
elif encoding:
|
elif encoding:
|
||||||
self.insertRule(cssutils.css.CSSCharsetRule(encoding=encoding), 0)
|
self.insertRule(cssutils.css.CSSCharsetRule(encoding=encoding), 0)
|
||||||
|
|
||||||
def _getEncoding(self):
|
|
||||||
"""Encoding set in :class:`~cssutils.css.CSSCharsetRule` or if ``None``
|
|
||||||
resulting in default ``utf-8`` encoding being used."""
|
|
||||||
try:
|
|
||||||
return self.cssRules[0].encoding
|
|
||||||
except (IndexError, AttributeError):
|
|
||||||
return 'utf-8'
|
|
||||||
|
|
||||||
encoding = property(_getEncoding, _setEncoding,
|
encoding = property(_getEncoding, _setEncoding,
|
||||||
"(cssutils) Reflect encoding of an @charset rule or 'utf-8' "
|
"(cssutils) Reflect encoding of an @charset rule or 'utf-8' "
|
||||||
"(default) if set to ``None``")
|
"(default) if set to ``None``")
|
||||||
@ -371,11 +382,11 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
self._checkReadonly()
|
self._checkReadonly()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
rule = self.cssRules[index]
|
rule = self._cssRules[index]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise xml.dom.IndexSizeErr(
|
raise xml.dom.IndexSizeErr(
|
||||||
u'CSSStyleSheet: %s is not a valid index in the rulelist of length %i' % (
|
u'CSSStyleSheet: %s is not a valid index in the rulelist of length %i' % (
|
||||||
index, self.cssRules.length))
|
index, self._cssRules.length))
|
||||||
else:
|
else:
|
||||||
if rule.type == rule.NAMESPACE_RULE:
|
if rule.type == rule.NAMESPACE_RULE:
|
||||||
# check all namespacerules if used
|
# check all namespacerules if used
|
||||||
@ -388,7 +399,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
return
|
return
|
||||||
|
|
||||||
rule._parentStyleSheet = None # detach
|
rule._parentStyleSheet = None # detach
|
||||||
del self.cssRules[index] # delete from StyleSheet
|
del self._cssRules[index] # delete from StyleSheet
|
||||||
|
|
||||||
def insertRule(self, rule, index=None, inOrder=False, _clean=True):
|
def insertRule(self, rule, index=None, inOrder=False, _clean=True):
|
||||||
"""
|
"""
|
||||||
@ -427,11 +438,11 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
|
|
||||||
# check position
|
# check position
|
||||||
if index is None:
|
if index is None:
|
||||||
index = len(self.cssRules)
|
index = len(self._cssRules)
|
||||||
elif index < 0 or index > self.cssRules.length:
|
elif index < 0 or index > self._cssRules.length:
|
||||||
raise xml.dom.IndexSizeErr(
|
raise xml.dom.IndexSizeErr(
|
||||||
u'CSSStyleSheet: Invalid index %s for CSSRuleList with a length of %s.' % (
|
u'CSSStyleSheet: Invalid index %s for CSSRuleList with a length of %s.' % (
|
||||||
index, self.cssRules.length))
|
index, self._cssRules.length))
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(rule, basestring):
|
if isinstance(rule, basestring):
|
||||||
@ -447,11 +458,11 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
# prepend encoding if in this sheet to be able to use it in
|
# prepend encoding if in this sheet to be able to use it in
|
||||||
# @import rules encoding resolution
|
# @import rules encoding resolution
|
||||||
# do not add if new rule startswith "@charset" (which is exact!)
|
# do not add if new rule startswith "@charset" (which is exact!)
|
||||||
if not rule.startswith(u'@charset') and (self.cssRules and
|
if not rule.startswith(u'@charset') and (self._cssRules and
|
||||||
self.cssRules[0].type == self.cssRules[0].CHARSET_RULE):
|
self._cssRules[0].type == self._cssRules[0].CHARSET_RULE):
|
||||||
# rule 0 is @charset!
|
# rule 0 is @charset!
|
||||||
newrulescount, newruleindex = 2, 1
|
newrulescount, newruleindex = 2, 1
|
||||||
rule = self.cssRules[0].cssText + rule
|
rule = self._cssRules[0].cssText + rule
|
||||||
else:
|
else:
|
||||||
newrulescount, newruleindex = 1, 0
|
newrulescount, newruleindex = 1, 0
|
||||||
|
|
||||||
@ -484,29 +495,29 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
if inOrder:
|
if inOrder:
|
||||||
index = 0
|
index = 0
|
||||||
# always first and only
|
# always first and only
|
||||||
if (self.cssRules and self.cssRules[0].type == rule.CHARSET_RULE):
|
if (self._cssRules and self._cssRules[0].type == rule.CHARSET_RULE):
|
||||||
self.cssRules[0].encoding = rule.encoding
|
self._cssRules[0].encoding = rule.encoding
|
||||||
else:
|
else:
|
||||||
self.cssRules.insert(0, rule)
|
self._cssRules.insert(0, rule)
|
||||||
elif index != 0 or (self.cssRules and
|
elif index != 0 or (self._cssRules and
|
||||||
self.cssRules[0].type == rule.CHARSET_RULE):
|
self._cssRules[0].type == rule.CHARSET_RULE):
|
||||||
self._log.error(
|
self._log.error(
|
||||||
u'CSSStylesheet: @charset only allowed once at the beginning of a stylesheet.',
|
u'CSSStylesheet: @charset only allowed once at the beginning of a stylesheet.',
|
||||||
error=xml.dom.HierarchyRequestErr)
|
error=xml.dom.HierarchyRequestErr)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.cssRules.insert(index, rule)
|
self._cssRules.insert(index, rule)
|
||||||
|
|
||||||
# @unknown or comment
|
# @unknown or comment
|
||||||
elif rule.type in (rule.UNKNOWN_RULE, rule.COMMENT) and not inOrder:
|
elif rule.type in (rule.UNKNOWN_RULE, rule.COMMENT) and not inOrder:
|
||||||
if index == 0 and self.cssRules and\
|
if index == 0 and self._cssRules and\
|
||||||
self.cssRules[0].type == rule.CHARSET_RULE:
|
self._cssRules[0].type == rule.CHARSET_RULE:
|
||||||
self._log.error(
|
self._log.error(
|
||||||
u'CSSStylesheet: @charset must be the first rule.',
|
u'CSSStylesheet: @charset must be the first rule.',
|
||||||
error=xml.dom.HierarchyRequestErr)
|
error=xml.dom.HierarchyRequestErr)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.cssRules.insert(index, rule)
|
self._cssRules.insert(index, rule)
|
||||||
|
|
||||||
# @import
|
# @import
|
||||||
elif rule.type == rule.IMPORT_RULE:
|
elif rule.type == rule.IMPORT_RULE:
|
||||||
@ -514,27 +525,27 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
# automatic order
|
# automatic order
|
||||||
if rule.type in (r.type for r in self):
|
if rule.type in (r.type for r in self):
|
||||||
# find last of this type
|
# find last of this type
|
||||||
for i, r in enumerate(reversed(self.cssRules)):
|
for i, r in enumerate(reversed(self._cssRules)):
|
||||||
if r.type == rule.type:
|
if r.type == rule.type:
|
||||||
index = len(self.cssRules) - i
|
index = len(self._cssRules) - i
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# find first point to insert
|
# find first point to insert
|
||||||
if self.cssRules and self.cssRules[0].type in (rule.CHARSET_RULE,
|
if self._cssRules and self._cssRules[0].type in (rule.CHARSET_RULE,
|
||||||
rule.COMMENT):
|
rule.COMMENT):
|
||||||
index = 1
|
index = 1
|
||||||
else:
|
else:
|
||||||
index = 0
|
index = 0
|
||||||
else:
|
else:
|
||||||
# after @charset
|
# after @charset
|
||||||
if index == 0 and self.cssRules and\
|
if index == 0 and self._cssRules and\
|
||||||
self.cssRules[0].type == rule.CHARSET_RULE:
|
self._cssRules[0].type == rule.CHARSET_RULE:
|
||||||
self._log.error(
|
self._log.error(
|
||||||
u'CSSStylesheet: Found @charset at index 0.',
|
u'CSSStylesheet: Found @charset at index 0.',
|
||||||
error=xml.dom.HierarchyRequestErr)
|
error=xml.dom.HierarchyRequestErr)
|
||||||
return
|
return
|
||||||
# before @namespace, @page, @font-face, @media and stylerule
|
# before @namespace, @page, @font-face, @media and stylerule
|
||||||
for r in self.cssRules[:index]:
|
for r in self._cssRules[:index]:
|
||||||
if r.type in (r.NAMESPACE_RULE, r.MEDIA_RULE, r.PAGE_RULE,
|
if r.type in (r.NAMESPACE_RULE, r.MEDIA_RULE, r.PAGE_RULE,
|
||||||
r.STYLE_RULE, r.FONT_FACE_RULE):
|
r.STYLE_RULE, r.FONT_FACE_RULE):
|
||||||
self._log.error(
|
self._log.error(
|
||||||
@ -542,27 +553,27 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
index,
|
index,
|
||||||
error=xml.dom.HierarchyRequestErr)
|
error=xml.dom.HierarchyRequestErr)
|
||||||
return
|
return
|
||||||
self.cssRules.insert(index, rule)
|
self._cssRules.insert(index, rule)
|
||||||
|
|
||||||
# @namespace
|
# @namespace
|
||||||
elif rule.type == rule.NAMESPACE_RULE:
|
elif rule.type == rule.NAMESPACE_RULE:
|
||||||
if inOrder:
|
if inOrder:
|
||||||
if rule.type in (r.type for r in self):
|
if rule.type in (r.type for r in self):
|
||||||
# find last of this type
|
# find last of this type
|
||||||
for i, r in enumerate(reversed(self.cssRules)):
|
for i, r in enumerate(reversed(self._cssRules)):
|
||||||
if r.type == rule.type:
|
if r.type == rule.type:
|
||||||
index = len(self.cssRules) - i
|
index = len(self._cssRules) - i
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# find first point to insert
|
# find first point to insert
|
||||||
for i, r in enumerate(self.cssRules):
|
for i, r in enumerate(self._cssRules):
|
||||||
if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE,
|
if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE,
|
||||||
r.FONT_FACE_RULE, r.UNKNOWN_RULE, r.COMMENT):
|
r.FONT_FACE_RULE, r.UNKNOWN_RULE, r.COMMENT):
|
||||||
index = i # before these
|
index = i # before these
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# after @charset and @import
|
# after @charset and @import
|
||||||
for r in self.cssRules[index:]:
|
for r in self._cssRules[index:]:
|
||||||
if r.type in (r.CHARSET_RULE, r.IMPORT_RULE):
|
if r.type in (r.CHARSET_RULE, r.IMPORT_RULE):
|
||||||
self._log.error(
|
self._log.error(
|
||||||
u'CSSStylesheet: Cannot insert @namespace here, found @charset or @import after index %s.' %
|
u'CSSStylesheet: Cannot insert @namespace here, found @charset or @import after index %s.' %
|
||||||
@ -570,7 +581,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
error=xml.dom.HierarchyRequestErr)
|
error=xml.dom.HierarchyRequestErr)
|
||||||
return
|
return
|
||||||
# before @media and stylerule
|
# before @media and stylerule
|
||||||
for r in self.cssRules[:index]:
|
for r in self._cssRules[:index]:
|
||||||
if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE,
|
if r.type in (r.MEDIA_RULE, r.PAGE_RULE, r.STYLE_RULE,
|
||||||
r.FONT_FACE_RULE):
|
r.FONT_FACE_RULE):
|
||||||
self._log.error(
|
self._log.error(
|
||||||
@ -582,7 +593,7 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
if not (rule.prefix in self.namespaces and
|
if not (rule.prefix in self.namespaces and
|
||||||
self.namespaces[rule.prefix] == rule.namespaceURI):
|
self.namespaces[rule.prefix] == rule.namespaceURI):
|
||||||
# no doublettes
|
# no doublettes
|
||||||
self.cssRules.insert(index, rule)
|
self._cssRules.insert(index, rule)
|
||||||
if _clean:
|
if _clean:
|
||||||
self._cleanNamespaces()
|
self._cleanNamespaces()
|
||||||
|
|
||||||
@ -590,17 +601,17 @@ class CSSStyleSheet(cssutils.stylesheets.StyleSheet):
|
|||||||
else:
|
else:
|
||||||
if inOrder:
|
if inOrder:
|
||||||
# simply add to end as no specific order
|
# simply add to end as no specific order
|
||||||
self.cssRules.append(rule)
|
self._cssRules.append(rule)
|
||||||
index = len(self.cssRules) - 1
|
index = len(self._cssRules) - 1
|
||||||
else:
|
else:
|
||||||
for r in self.cssRules[index:]:
|
for r in self._cssRules[index:]:
|
||||||
if r.type in (r.CHARSET_RULE, r.IMPORT_RULE, r.NAMESPACE_RULE):
|
if r.type in (r.CHARSET_RULE, r.IMPORT_RULE, r.NAMESPACE_RULE):
|
||||||
self._log.error(
|
self._log.error(
|
||||||
u'CSSStylesheet: Cannot insert rule here, found @charset, @import or @namespace before index %s.' %
|
u'CSSStylesheet: Cannot insert rule here, found @charset, @import or @namespace before index %s.' %
|
||||||
index,
|
index,
|
||||||
error=xml.dom.HierarchyRequestErr)
|
error=xml.dom.HierarchyRequestErr)
|
||||||
return
|
return
|
||||||
self.cssRules.insert(index, rule)
|
self._cssRules.insert(index, rule)
|
||||||
|
|
||||||
# post settings, TODO: for other rules which contain @rules
|
# post settings, TODO: for other rules which contain @rules
|
||||||
rule._parentStyleSheet = self
|
rule._parentStyleSheet = self
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"""
|
"""
|
||||||
__all__ = ['CSSValue', 'CSSPrimitiveValue', 'CSSValueList', 'RGBColor']
|
__all__ = ['CSSValue', 'CSSPrimitiveValue', 'CSSValueList', 'RGBColor']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssvalue.py 1684 2009-03-01 18:26:21Z cthedot $'
|
__version__ = '$Id: cssvalue.py 1834 2009-08-02 12:20:21Z cthedot $'
|
||||||
|
|
||||||
from cssutils.prodparser import *
|
from cssutils.prodparser import *
|
||||||
import cssutils
|
import cssutils
|
||||||
@ -81,6 +81,7 @@ class CSSValue(cssutils.util._NewBase):
|
|||||||
[ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
|
[ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |
|
||||||
TIME S* | FREQ S* ]
|
TIME S* | FREQ S* ]
|
||||||
| STRING S* | IDENT S* | URI S* | hexcolor | function
|
| STRING S* | IDENT S* | URI S* | hexcolor | function
|
||||||
|
| UNICODE-RANGE S*
|
||||||
;
|
;
|
||||||
function
|
function
|
||||||
: FUNCTION S* expr ')' S*
|
: FUNCTION S* expr ')' S*
|
||||||
@ -117,22 +118,25 @@ class CSSValue(cssutils.util._NewBase):
|
|||||||
PreDef.ident(nextSor=nextSor),
|
PreDef.ident(nextSor=nextSor),
|
||||||
PreDef.uri(nextSor=nextSor),
|
PreDef.uri(nextSor=nextSor),
|
||||||
PreDef.hexcolor(nextSor=nextSor),
|
PreDef.hexcolor(nextSor=nextSor),
|
||||||
|
PreDef.unicode_range(nextSor=nextSor),
|
||||||
# special case IE only expression
|
# special case IE only expression
|
||||||
Prod(name='expression',
|
Prod(name='expression',
|
||||||
match=lambda t, v: t == self._prods.FUNCTION and
|
match=lambda t, v: t == self._prods.FUNCTION and (
|
||||||
cssutils.helper.normalize(v) in (u'expression(',
|
cssutils.helper.normalize(v) in (u'expression(',
|
||||||
u'alpha('),
|
u'alpha(') or
|
||||||
|
v.startswith(u'progid:DXImageTransform.Microsoft.') ),
|
||||||
nextSor=nextSor,
|
nextSor=nextSor,
|
||||||
toSeq=lambda t, tokens: (ExpressionValue.name,
|
toSeq=lambda t, tokens: (ExpressionValue.name,
|
||||||
ExpressionValue(cssutils.helper.pushtoken(t,
|
ExpressionValue(cssutils.helper.pushtoken(t,
|
||||||
tokens)))),
|
tokens)))
|
||||||
|
),
|
||||||
PreDef.function(nextSor=nextSor,
|
PreDef.function(nextSor=nextSor,
|
||||||
toSeq=lambda t, tokens: ('FUNCTION',
|
toSeq=lambda t, tokens: ('FUNCTION',
|
||||||
CSSFunction(cssutils.helper.pushtoken(t,
|
CSSFunction(cssutils.helper.pushtoken(t,
|
||||||
tokens)))))
|
tokens)))))
|
||||||
operator = Choice(PreDef.S(optional=False, mayEnd=True),
|
operator = Choice(PreDef.S(),
|
||||||
PreDef.CHAR('comma', ',', toSeq=lambda t, tokens: ('operator', t[1])),
|
PreDef.char('comma', ',', toSeq=lambda t, tokens: ('operator', t[1])),
|
||||||
PreDef.CHAR('slash', '/', toSeq=lambda t, tokens: ('operator', t[1])),
|
PreDef.char('slash', '/', toSeq=lambda t, tokens: ('operator', t[1])),
|
||||||
optional=True)
|
optional=True)
|
||||||
# CSSValue PRODUCTIONS
|
# CSSValue PRODUCTIONS
|
||||||
valueprods = Sequence(term,
|
valueprods = Sequence(term,
|
||||||
@ -154,19 +158,22 @@ class CSSValue(cssutils.util._NewBase):
|
|||||||
item = seq[i]
|
item = seq[i]
|
||||||
if item.type == self._prods.S:
|
if item.type == self._prods.S:
|
||||||
pass
|
pass
|
||||||
elif item.value == u',' and item.type not in (self._prods.URI, self._prods.STRING):
|
|
||||||
# counts as a single one
|
elif (item.value, item.type) == (u',', 'operator'):
|
||||||
|
# , separared counts as a single STRING for now
|
||||||
|
# URI or STRING value might be a single CHAR too!
|
||||||
newseq.appendItem(item)
|
newseq.appendItem(item)
|
||||||
if firstvalue:
|
|
||||||
# may be IDENT or STRING but with , it is always STRING
|
|
||||||
firstvalue = firstvalue[0], 'STRING'
|
|
||||||
# each comma separated list counts as a single one only
|
|
||||||
count -= 1
|
count -= 1
|
||||||
|
if firstvalue:
|
||||||
|
# list of IDENTs is handled as STRING!
|
||||||
|
if firstvalue[1] == self._prods.IDENT:
|
||||||
|
firstvalue = firstvalue[0], 'STRING'
|
||||||
|
|
||||||
elif item.value == u'/':
|
elif item.value == u'/':
|
||||||
# counts as a single one
|
# / separated items count as one
|
||||||
newseq.appendItem(item)
|
newseq.appendItem(item)
|
||||||
|
|
||||||
elif item.value == u'+' or item.value == u'-':
|
elif item.value == u'-' or item.value == u'+':
|
||||||
# combine +- and following number or other
|
# combine +- and following number or other
|
||||||
i += 1
|
i += 1
|
||||||
try:
|
try:
|
||||||
@ -228,6 +235,8 @@ class CSSValue(cssutils.util._NewBase):
|
|||||||
return cssutils.helper.string(item.value)
|
return cssutils.helper.string(item.value)
|
||||||
elif self._prods.URI == item.type:
|
elif self._prods.URI == item.type:
|
||||||
return cssutils.helper.uri(item.value)
|
return cssutils.helper.uri(item.value)
|
||||||
|
elif self._prods.FUNCTION == item.type:
|
||||||
|
return item.value.cssText
|
||||||
else:
|
else:
|
||||||
return item.value
|
return item.value
|
||||||
|
|
||||||
@ -253,7 +262,8 @@ class CSSValue(cssutils.util._NewBase):
|
|||||||
self._prods.NUMBER,
|
self._prods.NUMBER,
|
||||||
self._prods.PERCENTAGE,
|
self._prods.PERCENTAGE,
|
||||||
self._prods.STRING,
|
self._prods.STRING,
|
||||||
self._prods.URI):
|
self._prods.URI,
|
||||||
|
self._prods.UNICODE_RANGE):
|
||||||
if nexttocommalist:
|
if nexttocommalist:
|
||||||
# wait until complete
|
# wait until complete
|
||||||
commalist.append(itemValue(item))
|
commalist.append(itemValue(item))
|
||||||
@ -353,6 +363,7 @@ class CSSPrimitiveValue(CSSValue):
|
|||||||
CSS_RGBCOLOR = 25
|
CSS_RGBCOLOR = 25
|
||||||
# NOT OFFICIAL:
|
# NOT OFFICIAL:
|
||||||
CSS_RGBACOLOR = 26
|
CSS_RGBACOLOR = 26
|
||||||
|
CSS_UNICODE_RANGE = 27
|
||||||
|
|
||||||
_floattypes = (CSS_NUMBER, CSS_PERCENTAGE, CSS_EMS, CSS_EXS,
|
_floattypes = (CSS_NUMBER, CSS_PERCENTAGE, CSS_EMS, CSS_EXS,
|
||||||
CSS_PX, CSS_CM, CSS_MM, CSS_IN, CSS_PT, CSS_PC,
|
CSS_PX, CSS_CM, CSS_MM, CSS_IN, CSS_PT, CSS_PC,
|
||||||
@ -429,6 +440,7 @@ class CSSPrimitiveValue(CSSValue):
|
|||||||
'CSS_STRING', 'CSS_URI', 'CSS_IDENT',
|
'CSS_STRING', 'CSS_URI', 'CSS_IDENT',
|
||||||
'CSS_ATTR', 'CSS_COUNTER', 'CSS_RECT',
|
'CSS_ATTR', 'CSS_COUNTER', 'CSS_RECT',
|
||||||
'CSS_RGBCOLOR', 'CSS_RGBACOLOR',
|
'CSS_RGBCOLOR', 'CSS_RGBACOLOR',
|
||||||
|
'CSS_UNICODE_RANGE'
|
||||||
]
|
]
|
||||||
|
|
||||||
_reNumDim = re.compile(ur'([+-]?\d*\.\d+|[+-]?\d+)(.*)$', re.I| re.U|re.X)
|
_reNumDim = re.compile(ur'([+-]?\d*\.\d+|[+-]?\d+)(.*)$', re.I| re.U|re.X)
|
||||||
@ -464,6 +476,7 @@ class CSSPrimitiveValue(CSSValue):
|
|||||||
__types.NUMBER: 'CSS_NUMBER',
|
__types.NUMBER: 'CSS_NUMBER',
|
||||||
__types.PERCENTAGE: 'CSS_PERCENTAGE',
|
__types.PERCENTAGE: 'CSS_PERCENTAGE',
|
||||||
__types.STRING: 'CSS_STRING',
|
__types.STRING: 'CSS_STRING',
|
||||||
|
__types.UNICODE_RANGE: 'CSS_UNICODE_RANGE',
|
||||||
__types.URI: 'CSS_URI',
|
__types.URI: 'CSS_URI',
|
||||||
__types.IDENT: 'CSS_IDENT',
|
__types.IDENT: 'CSS_IDENT',
|
||||||
__types.HASH: 'CSS_RGBCOLOR',
|
__types.HASH: 'CSS_RGBCOLOR',
|
||||||
@ -474,7 +487,6 @@ class CSSPrimitiveValue(CSSValue):
|
|||||||
def __set_primitiveType(self):
|
def __set_primitiveType(self):
|
||||||
"""primitiveType is readonly but is set lazy if accessed"""
|
"""primitiveType is readonly but is set lazy if accessed"""
|
||||||
# TODO: check unary and font-family STRING a, b, "c"
|
# TODO: check unary and font-family STRING a, b, "c"
|
||||||
|
|
||||||
val, type_ = self._value
|
val, type_ = self._value
|
||||||
# try get by type_
|
# try get by type_
|
||||||
pt = self.__unitbytype.get(type_, 'CSS_UNKNOWN')
|
pt = self.__unitbytype.get(type_, 'CSS_UNKNOWN')
|
||||||
@ -969,23 +981,31 @@ class RGBColor(CSSPrimitiveValue):
|
|||||||
|
|
||||||
class ExpressionValue(CSSFunction):
|
class ExpressionValue(CSSFunction):
|
||||||
"""Special IE only CSSFunction which may contain *anything*.
|
"""Special IE only CSSFunction which may contain *anything*.
|
||||||
Used for expressions and ``alpha(opacity=100)`` currently"""
|
Used for expressions and ``alpha(opacity=100)`` currently."""
|
||||||
name = u'Expression (IE only)'
|
name = u'Expression (IE only)'
|
||||||
|
|
||||||
def _productiondefinition(self):
|
def _productiondefinition(self):
|
||||||
"""Return defintion used for parsing."""
|
"""Return defintion used for parsing."""
|
||||||
types = self._prods # rename!
|
types = self._prods # rename!
|
||||||
|
|
||||||
|
def toSeq(t, tokens):
|
||||||
|
"Do not normalize function name!"
|
||||||
|
return t[0], t[1]
|
||||||
|
|
||||||
funcProds = Sequence(Prod(name='expression',
|
funcProds = Sequence(Prod(name='expression',
|
||||||
match=lambda t, v: t == types.FUNCTION,
|
match=lambda t, v: t == types.FUNCTION,
|
||||||
toSeq=lambda t, tokens: (t[0], cssutils.helper.normalize(t[1]))),
|
toSeq=toSeq
|
||||||
|
),
|
||||||
Sequence(Choice(Prod(name='nested function',
|
Sequence(Choice(Prod(name='nested function',
|
||||||
match=lambda t, v: t == self._prods.FUNCTION,
|
match=lambda t, v: t == self._prods.FUNCTION,
|
||||||
toSeq=lambda t, tokens: (CSSFunction.name,
|
toSeq=lambda t, tokens: (CSSFunction.name,
|
||||||
CSSFunction(cssutils.helper.pushtoken(t,
|
CSSFunction(cssutils.helper.pushtoken(t,
|
||||||
tokens)))),
|
tokens)))
|
||||||
|
),
|
||||||
Prod(name='part',
|
Prod(name='part',
|
||||||
match=lambda t, v: v != u')',
|
match=lambda t, v: v != u')',
|
||||||
toSeq=lambda t, tokens: (t[0], t[1])), ),
|
toSeq=lambda t, tokens: (t[0], t[1])),
|
||||||
|
),
|
||||||
minmax=lambda: (0, None)),
|
minmax=lambda: (0, None)),
|
||||||
PreDef.funcEnd(stop=True))
|
PreDef.funcEnd(stop=True))
|
||||||
return funcProds
|
return funcProds
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Property is a single CSS property in a CSSStyleDeclaration."""
|
"""Property is a single CSS property in a CSSStyleDeclaration."""
|
||||||
__all__ = ['Property']
|
__all__ = ['Property']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: property.py 1685 2009-03-01 18:26:48Z cthedot $'
|
__version__ = '$Id: property.py 1811 2009-07-29 13:11:15Z cthedot $'
|
||||||
|
|
||||||
from cssutils.helper import Deprecated
|
from cssutils.helper import Deprecated
|
||||||
from cssvalue import CSSValue
|
from cssvalue import CSSValue
|
||||||
@ -44,7 +44,7 @@ class Property(cssutils.util.Base):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, name=None, value=None, priority=u'',
|
def __init__(self, name=None, value=None, priority=u'',
|
||||||
_mediaQuery=False, _parent=None):
|
_mediaQuery=False, parent=None, parentStyle=None):
|
||||||
"""
|
"""
|
||||||
:param name:
|
:param name:
|
||||||
a property name string (will be normalized)
|
a property name string (will be normalized)
|
||||||
@ -55,16 +55,17 @@ class Property(cssutils.util.Base):
|
|||||||
u'!important' or u'important'
|
u'!important' or u'important'
|
||||||
:param _mediaQuery:
|
:param _mediaQuery:
|
||||||
if ``True`` value is optional (used by MediaQuery)
|
if ``True`` value is optional (used by MediaQuery)
|
||||||
:param _parent:
|
:param parent:
|
||||||
the parent object, normally a
|
the parent object, normally a
|
||||||
:class:`cssutils.css.CSSStyleDeclaration`
|
:class:`cssutils.css.CSSStyleDeclaration`
|
||||||
|
:param parentStyle:
|
||||||
|
DEPRECATED: Use ``parent`` instead
|
||||||
"""
|
"""
|
||||||
super(Property, self).__init__()
|
super(Property, self).__init__()
|
||||||
|
|
||||||
self.seqs = [[], None, []]
|
self.seqs = [[], None, []]
|
||||||
self.wellformed = False
|
self.wellformed = False
|
||||||
self._mediaQuery = _mediaQuery
|
self._mediaQuery = _mediaQuery
|
||||||
self._parent = _parent
|
self.parent = parent
|
||||||
|
|
||||||
self.__nametoken = None
|
self.__nametoken = None
|
||||||
self._name = u''
|
self._name = u''
|
||||||
@ -363,12 +364,17 @@ class Property(cssutils.util.Base):
|
|||||||
literalpriority = property(lambda self: self._literalpriority,
|
literalpriority = property(lambda self: self._literalpriority,
|
||||||
doc="Readonly literal (not normalized) priority of this property")
|
doc="Readonly literal (not normalized) priority of this property")
|
||||||
|
|
||||||
def validate(self, profiles=None):
|
def _setParent(self, parent):
|
||||||
"""Validate value against `profiles`.
|
self._parent = parent
|
||||||
|
|
||||||
:param profiles:
|
parent = property(lambda self: self._parent, _setParent,
|
||||||
A list of profile names used for validating. If no `profiles`
|
doc="The Parent Node (normally a CSSStyledeclaration) of this "
|
||||||
is given ``cssutils.profile.defaultProfiles`` is used
|
"Property")
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
"""Validate value against `profiles` which are checked dynamically.
|
||||||
|
properties in e.g. @font-face rules are checked against
|
||||||
|
``cssutils.profile.CSS3_FONT_FACE`` only.
|
||||||
|
|
||||||
For each of the following cases a message is reported:
|
For each of the following cases a message is reported:
|
||||||
|
|
||||||
@ -424,6 +430,16 @@ class Property(cssutils.util.Base):
|
|||||||
"""
|
"""
|
||||||
valid = False
|
valid = False
|
||||||
|
|
||||||
|
profiles = None
|
||||||
|
try:
|
||||||
|
# if @font-face use that profile
|
||||||
|
rule = self.parent.parentRule
|
||||||
|
if rule.type == rule.FONT_FACE_RULE:
|
||||||
|
profiles = [cssutils.profile.CSS3_FONT_FACE]
|
||||||
|
#TODO: same for @page
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
if self.name and self.value:
|
if self.name and self.value:
|
||||||
|
|
||||||
if self.name in cssutils.profile.knownNames:
|
if self.name in cssutils.profile.knownNames:
|
||||||
@ -467,3 +483,12 @@ class Property(cssutils.util.Base):
|
|||||||
|
|
||||||
valid = property(validate, doc="Check if value of this property is valid "
|
valid = property(validate, doc="Check if value of this property is valid "
|
||||||
"in the properties context.")
|
"in the properties context.")
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated('Use ``parent`` attribute instead.')
|
||||||
|
def _getParentStyle(self):
|
||||||
|
return self._parent
|
||||||
|
|
||||||
|
parentStyle = property(_getParentStyle, _setParent,
|
||||||
|
doc="DEPRECATED: Use ``parent`` instead")
|
||||||
|
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
"""productions for CSS 3
|
|
||||||
|
|
||||||
CSS3_MACROS and CSS3_PRODUCTIONS are from http://www.w3.org/TR/css3-syntax
|
|
||||||
"""
|
|
||||||
__all__ = ['CSSProductions', 'MACROS', 'PRODUCTIONS']
|
|
||||||
__docformat__ = 'restructuredtext'
|
|
||||||
__version__ = '$Id: css3productions.py 1116 2008-03-05 13:52:23Z cthedot $'
|
|
||||||
|
|
||||||
# a complete list of css3 macros
|
|
||||||
MACROS = {
|
|
||||||
'ident': r'[-]?{nmstart}{nmchar}*',
|
|
||||||
'name': r'{nmchar}+',
|
|
||||||
'nmstart': r'[_a-zA-Z]|{nonascii}|{escape}',
|
|
||||||
'nonascii': r'[^\0-\177]',
|
|
||||||
'unicode': r'\\[0-9a-f]{1,6}{wc}?',
|
|
||||||
'escape': r'{unicode}|\\[ -~\200-\777]',
|
|
||||||
# 'escape': r'{unicode}|\\[ -~\200-\4177777]',
|
|
||||||
'nmchar': r'[-_a-zA-Z0-9]|{nonascii}|{escape}',
|
|
||||||
|
|
||||||
# CHANGED TO SPEC: added "-?"
|
|
||||||
'num': r'-?[0-9]*\.[0-9]+|[0-9]+', #r'[-]?\d+|[-]?\d*\.\d+',
|
|
||||||
'string': r'''\'({stringchar}|\")*\'|\"({stringchar}|\')*\"''',
|
|
||||||
'stringchar': r'{urlchar}| |\\{nl}',
|
|
||||||
'urlchar': r'[\x09\x21\x23-\x26\x27-\x7E]|{nonascii}|{escape}',
|
|
||||||
# what if \r\n, \n matches first?
|
|
||||||
'nl': r'\n|\r\n|\r|\f',
|
|
||||||
'w': r'{wc}*',
|
|
||||||
'wc': r'\t|\r|\n|\f|\x20'
|
|
||||||
}
|
|
||||||
|
|
||||||
# The following productions are the complete list of tokens in CSS3, the productions are **ordered**:
|
|
||||||
PRODUCTIONS = [
|
|
||||||
('BOM', r'\xFEFF'),
|
|
||||||
('URI', r'url\({w}({string}|{urlchar}*){w}\)'),
|
|
||||||
('FUNCTION', r'{ident}\('),
|
|
||||||
('ATKEYWORD', r'\@{ident}'),
|
|
||||||
('IDENT', r'{ident}'),
|
|
||||||
('STRING', r'{string}'),
|
|
||||||
('HASH', r'\#{name}'),
|
|
||||||
('PERCENTAGE', r'{num}\%'),
|
|
||||||
('DIMENSION', r'{num}{ident}'),
|
|
||||||
('NUMBER', r'{num}'),
|
|
||||||
#???
|
|
||||||
('UNICODE-RANGE', ur'[0-9A-F?]{1,6}(\-[0-9A-F]{1,6})?'),
|
|
||||||
('CDO', r'\<\!\-\-'),
|
|
||||||
('CDC', r'\-\-\>'),
|
|
||||||
('S', r'{wc}+'),
|
|
||||||
('INCLUDES', '\~\='),
|
|
||||||
('DASHMATCH', r'\|\='),
|
|
||||||
('PREFIXMATCH', r'\^\='),
|
|
||||||
('SUFFIXMATCH', r'\$\='),
|
|
||||||
('SUBSTRINGMATCH', r'\*\='),
|
|
||||||
('COMMENT', r'\/\*[^*]*\*+([^/][^*]*\*+)*\/'),
|
|
||||||
('CHAR', r'[^"\']'),
|
|
||||||
]
|
|
||||||
|
|
||||||
class CSSProductions(object):
|
|
||||||
"has attributes for all PRODUCTIONS"
|
|
||||||
pass
|
|
||||||
|
|
||||||
for i, t in enumerate(PRODUCTIONS):
|
|
||||||
setattr(CSSProductions, t[0].replace('-', '_'), t[0])
|
|
@ -12,12 +12,12 @@ open issues
|
|||||||
"""
|
"""
|
||||||
__all__ = ['CSSProductions', 'MACROS', 'PRODUCTIONS']
|
__all__ = ['CSSProductions', 'MACROS', 'PRODUCTIONS']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: cssproductions.py 1738 2009-05-02 13:03:28Z cthedot $'
|
__version__ = '$Id: cssproductions.py 1835 2009-08-02 16:47:27Z cthedot $'
|
||||||
|
|
||||||
# a complete list of css3 macros
|
# a complete list of css3 macros
|
||||||
MACROS = {
|
MACROS = {
|
||||||
'nonascii': r'[^\0-\177]',
|
'nonascii': r'[^\0-\177]',
|
||||||
'unicode': r'\\[0-9a-f]{1,6}(?:{nl}|{s})?',
|
'unicode': r'\\[0-9A-Fa-f]{1,6}(?:{nl}|{s})?',
|
||||||
#'escape': r'{unicode}|\\[ -~\200-\777]',
|
#'escape': r'{unicode}|\\[ -~\200-\777]',
|
||||||
'escape': r'{unicode}|\\[^\n\r\f0-9a-f]',
|
'escape': r'{unicode}|\\[^\n\r\f0-9a-f]',
|
||||||
'nmstart': r'[_a-zA-Z]|{nonascii}|{escape}',
|
'nmstart': r'[_a-zA-Z]|{nonascii}|{escape}',
|
||||||
@ -71,6 +71,7 @@ PRODUCTIONS = [
|
|||||||
('S', r'{s}+'), # 1st in list of general productions
|
('S', r'{s}+'), # 1st in list of general productions
|
||||||
('URI', r'{U}{R}{L}\({w}({string}|{url}*){w}\)'),
|
('URI', r'{U}{R}{L}\({w}({string}|{url}*){w}\)'),
|
||||||
('FUNCTION', r'{ident}\('),
|
('FUNCTION', r'{ident}\('),
|
||||||
|
('UNICODE-RANGE', r'{U}\+[0-9A-Fa-f?]{1,6}(\-[0-9A-Fa-f]{1,6})?'),
|
||||||
('IDENT', r'{ident}'),
|
('IDENT', r'{ident}'),
|
||||||
('STRING', r'{string}'),
|
('STRING', r'{string}'),
|
||||||
('INVALID', r'{invalid}'), # from CSS2.1
|
('INVALID', r'{invalid}'), # from CSS2.1
|
||||||
@ -80,8 +81,9 @@ PRODUCTIONS = [
|
|||||||
('NUMBER', r'{num}'),
|
('NUMBER', r'{num}'),
|
||||||
# valid ony at start so not checked everytime
|
# valid ony at start so not checked everytime
|
||||||
#('CHARSET_SYM', r'@charset '), # from Errata includes ending space!
|
#('CHARSET_SYM', r'@charset '), # from Errata includes ending space!
|
||||||
|
# checked specially if fullsheet is parsed
|
||||||
|
('COMMENT', r'{comment}'), #r'\/\*[^*]*\*+([^/][^*]*\*+)*\/'),
|
||||||
('ATKEYWORD', r'@{ident}'), # other keywords are done in the tokenizer
|
('ATKEYWORD', r'@{ident}'), # other keywords are done in the tokenizer
|
||||||
#('UNICODE-RANGE', r'[0-9A-F?]{1,6}(\-[0-9A-F]{1,6})?'), #???
|
|
||||||
('CDO', r'\<\!\-\-'),
|
('CDO', r'\<\!\-\-'),
|
||||||
('CDC', r'\-\-\>'),
|
('CDC', r'\-\-\>'),
|
||||||
('INCLUDES', '\~\='),
|
('INCLUDES', '\~\='),
|
||||||
@ -89,8 +91,6 @@ PRODUCTIONS = [
|
|||||||
('PREFIXMATCH', r'\^\='),
|
('PREFIXMATCH', r'\^\='),
|
||||||
('SUFFIXMATCH', r'\$\='),
|
('SUFFIXMATCH', r'\$\='),
|
||||||
('SUBSTRINGMATCH', r'\*\='),
|
('SUBSTRINGMATCH', r'\*\='),
|
||||||
# checked specially if fullsheet is parsed
|
|
||||||
('COMMENT', r'{comment}'), #r'\/\*[^*]*\*+([^/][^*]*\*+)*\/'),
|
|
||||||
('CHAR', r'[^"\']') # MUST always be last
|
('CHAR', r'[^"\']') # MUST always be last
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -110,3 +110,9 @@ class CSSProductions(object):
|
|||||||
|
|
||||||
for i, t in enumerate(PRODUCTIONS):
|
for i, t in enumerate(PRODUCTIONS):
|
||||||
setattr(CSSProductions, t[0].replace('-', '_'), t[0])
|
setattr(CSSProductions, t[0].replace('-', '_'), t[0])
|
||||||
|
|
||||||
|
|
||||||
|
# may be enabled by settings.set
|
||||||
|
_DXImageTransform = ('FUNCTION',
|
||||||
|
r'progid\:DXImageTransform\.Microsoft\..+\('
|
||||||
|
)
|
||||||
|
@ -16,7 +16,7 @@ log
|
|||||||
"""
|
"""
|
||||||
__all__ = ['ErrorHandler']
|
__all__ = ['ErrorHandler']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: errorhandler.py 1728 2009-05-01 20:35:25Z cthedot $'
|
__version__ = '$Id: errorhandler.py 1812 2009-07-29 13:11:49Z cthedot $'
|
||||||
|
|
||||||
from helper import Deprecated
|
from helper import Deprecated
|
||||||
import logging
|
import logging
|
||||||
@ -41,6 +41,9 @@ class _ErrorHandler(object):
|
|||||||
- False: Errors will be written to the log, this is the
|
- False: Errors will be written to the log, this is the
|
||||||
default behaviour when parsing
|
default behaviour when parsing
|
||||||
"""
|
"""
|
||||||
|
# may be disabled during setting of known valid items
|
||||||
|
self.enabled = True
|
||||||
|
|
||||||
if log:
|
if log:
|
||||||
self._log = log
|
self._log = log
|
||||||
else:
|
else:
|
||||||
@ -74,6 +77,7 @@ class _ErrorHandler(object):
|
|||||||
handles all calls
|
handles all calls
|
||||||
logs or raises exception
|
logs or raises exception
|
||||||
"""
|
"""
|
||||||
|
if self.enabled:
|
||||||
line, col = None, None
|
line, col = None, None
|
||||||
if token:
|
if token:
|
||||||
if isinstance(token, tuple):
|
if isinstance(token, tuple):
|
||||||
@ -89,8 +93,8 @@ class _ErrorHandler(object):
|
|||||||
elif issubclass(error, xml.dom.DOMException):
|
elif issubclass(error, xml.dom.DOMException):
|
||||||
error.line = line
|
error.line = line
|
||||||
error.col = col
|
error.col = col
|
||||||
# raise error(msg, line, col)
|
# raise error(msg, line, col)
|
||||||
# else:
|
# else:
|
||||||
raise error(msg)
|
raise error(msg)
|
||||||
else:
|
else:
|
||||||
self._logcall(msg)
|
self._logcall(msg)
|
||||||
|
@ -3,7 +3,10 @@
|
|||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: errorhandler.py 1234 2008-05-22 20:26:12Z cthedot $'
|
__version__ = '$Id: errorhandler.py 1234 2008-05-22 20:26:12Z cthedot $'
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
|
import urllib
|
||||||
|
|
||||||
class Deprecated(object):
|
class Deprecated(object):
|
||||||
"""This is a decorator which can be used to mark functions
|
"""This is a decorator which can be used to mark functions
|
||||||
@ -48,6 +51,10 @@ def normalize(x):
|
|||||||
else:
|
else:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
def path2url(path):
|
||||||
|
"""Return file URL of `path`"""
|
||||||
|
return u'file:' + urllib.pathname2url(os.path.abspath(path))
|
||||||
|
|
||||||
def pushtoken(token, tokens):
|
def pushtoken(token, tokens):
|
||||||
"""Return new generator starting with token followed by all tokens in
|
"""Return new generator starting with token followed by all tokens in
|
||||||
``tokens``"""
|
``tokens``"""
|
||||||
@ -107,24 +114,24 @@ def urivalue(uri):
|
|||||||
else:
|
else:
|
||||||
return uri
|
return uri
|
||||||
|
|
||||||
def normalnumber(num):
|
#def normalnumber(num):
|
||||||
"""
|
# """
|
||||||
Return normalized number as string.
|
# Return normalized number as string.
|
||||||
"""
|
# """
|
||||||
sign = ''
|
# sign = ''
|
||||||
if num.startswith('-'):
|
# if num.startswith('-'):
|
||||||
sign = '-'
|
# sign = '-'
|
||||||
num = num[1:]
|
# num = num[1:]
|
||||||
elif num.startswith('+'):
|
# elif num.startswith('+'):
|
||||||
num = num[1:]
|
# num = num[1:]
|
||||||
|
#
|
||||||
if float(num) == 0.0:
|
# if float(num) == 0.0:
|
||||||
return '0'
|
# return '0'
|
||||||
else:
|
# else:
|
||||||
if num.find('.') == -1:
|
# if num.find('.') == -1:
|
||||||
return sign + str(int(num))
|
# return sign + str(int(num))
|
||||||
else:
|
# else:
|
||||||
a, b = num.split('.')
|
# a, b = num.split('.')
|
||||||
if not a:
|
# if not a:
|
||||||
a = '0'
|
# a = '0'
|
||||||
return '%s%s.%s' % (sign, int(a), b)
|
# return '%s%s.%s' % (sign, int(a), b)
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
"""A validating CSSParser"""
|
"""A validating CSSParser"""
|
||||||
__all__ = ['CSSParser']
|
__all__ = ['CSSParser']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: parse.py 1656 2009-02-03 20:31:06Z cthedot $'
|
__version__ = '$Id: parse.py 1754 2009-05-30 14:50:13Z cthedot $'
|
||||||
|
|
||||||
from helper import Deprecated
|
from helper import Deprecated, path2url
|
||||||
import codecs
|
import codecs
|
||||||
import cssutils
|
import cssutils
|
||||||
import os
|
import os
|
||||||
@ -124,7 +124,8 @@ class CSSParser(object):
|
|||||||
"""
|
"""
|
||||||
if not href:
|
if not href:
|
||||||
# prepend // for file URL, urllib does not do this?
|
# prepend // for file URL, urllib does not do this?
|
||||||
href = u'file:' + urllib.pathname2url(os.path.abspath(filename))
|
#href = u'file:' + urllib.pathname2url(os.path.abspath(filename))
|
||||||
|
href = path2url(filename)
|
||||||
|
|
||||||
return self.parseString(open(filename, 'rb').read(),
|
return self.parseString(open(filename, 'rb').read(),
|
||||||
encoding=encoding, # read returns a str
|
encoding=encoding, # read returns a str
|
||||||
|
@ -533,105 +533,98 @@ class PreDef(object):
|
|||||||
types = cssutils.cssproductions.CSSProductions
|
types = cssutils.cssproductions.CSSProductions
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def CHAR(name='char', char=u',', toSeq=None, toStore=None, stop=False,
|
def char(name='char', char=u',', toSeq=None, stop=False,
|
||||||
nextSor=False):
|
nextSor=False):
|
||||||
"any CHAR"
|
"any CHAR"
|
||||||
return Prod(name=name, match=lambda t, v: v == char,
|
return Prod(name=name, match=lambda t, v: v == char,
|
||||||
toSeq=toSeq,
|
toSeq=toSeq,
|
||||||
toStore=toStore,
|
|
||||||
stop=stop,
|
stop=stop,
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def comma(toStore=None):
|
def comma():
|
||||||
return PreDef.CHAR(u'comma', u',', toStore=toStore)
|
return PreDef.char(u'comma', u',')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dimension(toStore=None, nextSor=False):
|
def dimension(nextSor=False):
|
||||||
return Prod(name=u'dimension',
|
return Prod(name=u'dimension',
|
||||||
match=lambda t, v: t == PreDef.types.DIMENSION,
|
match=lambda t, v: t == PreDef.types.DIMENSION,
|
||||||
toStore=toStore,
|
|
||||||
toSeq=lambda t, tokens: (t[0], cssutils.helper.normalize(t[1])),
|
toSeq=lambda t, tokens: (t[0], cssutils.helper.normalize(t[1])),
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def function(toSeq=None, toStore=None, nextSor=False):
|
def function(toSeq=None, nextSor=False):
|
||||||
return Prod(name=u'function',
|
return Prod(name=u'function',
|
||||||
match=lambda t, v: t == PreDef.types.FUNCTION,
|
match=lambda t, v: t == PreDef.types.FUNCTION,
|
||||||
toSeq=toSeq,
|
toSeq=toSeq,
|
||||||
toStore=toStore,
|
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def funcEnd(toStore=None, stop=False, nextSor=False):
|
def funcEnd(stop=False):
|
||||||
")"
|
")"
|
||||||
return PreDef.CHAR(u'end FUNC ")"', u')',
|
return PreDef.char(u'end FUNC ")"', u')',
|
||||||
toStore=toStore,
|
stop=stop)
|
||||||
stop=stop,
|
|
||||||
nextSor=nextSor)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ident(toStore=None, nextSor=False):
|
def ident(nextSor=False):
|
||||||
return Prod(name=u'ident',
|
return Prod(name=u'ident',
|
||||||
match=lambda t, v: t == PreDef.types.IDENT,
|
match=lambda t, v: t == PreDef.types.IDENT,
|
||||||
toStore=toStore,
|
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def number(toStore=None, nextSor=False):
|
def number(nextSor=False):
|
||||||
return Prod(name=u'number',
|
return Prod(name=u'number',
|
||||||
match=lambda t, v: t == PreDef.types.NUMBER,
|
match=lambda t, v: t == PreDef.types.NUMBER,
|
||||||
toStore=toStore,
|
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def string(toStore=None, nextSor=False):
|
def string(nextSor=False):
|
||||||
"string delimiters are removed by default"
|
"string delimiters are removed by default"
|
||||||
return Prod(name=u'string',
|
return Prod(name=u'string',
|
||||||
match=lambda t, v: t == PreDef.types.STRING,
|
match=lambda t, v: t == PreDef.types.STRING,
|
||||||
toStore=toStore,
|
|
||||||
toSeq=lambda t, tokens: (t[0], cssutils.helper.stringvalue(t[1])),
|
toSeq=lambda t, tokens: (t[0], cssutils.helper.stringvalue(t[1])),
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def percentage(toStore=None, nextSor=False):
|
def percentage(nextSor=False):
|
||||||
return Prod(name=u'percentage',
|
return Prod(name=u'percentage',
|
||||||
match=lambda t, v: t == PreDef.types.PERCENTAGE,
|
match=lambda t, v: t == PreDef.types.PERCENTAGE,
|
||||||
toStore=toStore,
|
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def S(name=u'whitespace', optional=True, toSeq=None, toStore=None, nextSor=False,
|
def S():
|
||||||
mayEnd=False):
|
return Prod(name=u'whitespace',
|
||||||
return Prod(name=name,
|
|
||||||
match=lambda t, v: t == PreDef.types.S,
|
match=lambda t, v: t == PreDef.types.S,
|
||||||
optional=optional,
|
mayEnd=True)
|
||||||
toSeq=toSeq,
|
|
||||||
toStore=toStore,
|
|
||||||
mayEnd=mayEnd)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def unary(optional=True, toStore=None):
|
def unary():
|
||||||
"+ or -"
|
"+ or -"
|
||||||
return Prod(name=u'unary +-', match=lambda t, v: v in (u'+', u'-'),
|
return Prod(name=u'unary +-', match=lambda t, v: v in (u'+', u'-'),
|
||||||
optional=optional,
|
optional=True)
|
||||||
toStore=toStore)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def uri(toStore=None, nextSor=False):
|
def uri(nextSor=False):
|
||||||
"'url(' and ')' are removed and URI is stripped"
|
"'url(' and ')' are removed and URI is stripped"
|
||||||
return Prod(name=u'URI',
|
return Prod(name=u'URI',
|
||||||
match=lambda t, v: t == PreDef.types.URI,
|
match=lambda t, v: t == PreDef.types.URI,
|
||||||
toStore=toStore,
|
|
||||||
toSeq=lambda t, tokens: (t[0], cssutils.helper.urivalue(t[1])),
|
toSeq=lambda t, tokens: (t[0], cssutils.helper.urivalue(t[1])),
|
||||||
nextSor=nextSor)
|
nextSor=nextSor)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def hexcolor(toStore=None, toSeq=None, nextSor=False):
|
def hexcolor(nextSor=False):
|
||||||
|
"#123456"
|
||||||
return Prod(name='HEX color',
|
return Prod(name='HEX color',
|
||||||
match=lambda t, v: t == PreDef.types.HASH and
|
match=lambda t, v: t == PreDef.types.HASH and (
|
||||||
len(v) == 4 or len(v) == 7,
|
len(v) == 4 or len(v) == 7),
|
||||||
toStore=toStore,
|
nextSor=nextSor
|
||||||
toSeq=toSeq,
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def unicode_range(nextSor=False):
|
||||||
|
"u+123456-abc normalized to lower `u`"
|
||||||
|
return Prod(name='unicode-range',
|
||||||
|
match=lambda t, v: t == PreDef.types.UNICODE_RANGE,
|
||||||
|
toSeq=lambda t, tokens: (t[0], t[1].lower()),
|
||||||
nextSor=nextSor
|
nextSor=nextSor
|
||||||
)
|
)
|
||||||
|
@ -43,8 +43,10 @@ class Profiles(object):
|
|||||||
macros.
|
macros.
|
||||||
"""
|
"""
|
||||||
CSS_LEVEL_2 = 'CSS Level 2.1'
|
CSS_LEVEL_2 = 'CSS Level 2.1'
|
||||||
CSS3_COLOR = CSS_COLOR_LEVEL_3 = 'CSS Color Module Level 3'
|
|
||||||
CSS3_BOX = CSS_BOX_LEVEL_3 = 'CSS Box Module Level 3'
|
CSS3_BOX = CSS_BOX_LEVEL_3 = 'CSS Box Module Level 3'
|
||||||
|
CSS3_COLOR = CSS_COLOR_LEVEL_3 = 'CSS Color Module Level 3'
|
||||||
|
CSS3_FONTS = 'CSS Fonts Module Level 3'
|
||||||
|
CSS3_FONT_FACE = 'CSS Fonts Module Level 3 @font-face properties'
|
||||||
CSS3_PAGED_MEDIA = 'CSS3 Paged Media Module'
|
CSS3_PAGED_MEDIA = 'CSS3 Paged Media Module'
|
||||||
|
|
||||||
_TOKEN_MACROS = {
|
_TOKEN_MACROS = {
|
||||||
@ -58,6 +60,7 @@ class Profiles(object):
|
|||||||
'int': r'[-]?\d+',
|
'int': r'[-]?\d+',
|
||||||
'nmchar': r'[\w-]|{nonascii}|{escape}',
|
'nmchar': r'[\w-]|{nonascii}|{escape}',
|
||||||
'num': r'[-]?\d+|[-]?\d*\.\d+',
|
'num': r'[-]?\d+|[-]?\d*\.\d+',
|
||||||
|
'positivenum': r'\d+|[-]?\d*\.\d+',
|
||||||
'number': r'{num}',
|
'number': r'{num}',
|
||||||
'string': r'{string1}|{string2}',
|
'string': r'{string1}|{string2}',
|
||||||
'string1': r'"(\\\"|[^\"])*"',
|
'string1': r'"(\\\"|[^\"])*"',
|
||||||
@ -75,6 +78,7 @@ class Profiles(object):
|
|||||||
#'color': r'(maroon|red|orange|yellow|olive|purple|fuchsia|white|lime|green|navy|blue|aqua|teal|black|silver|gray|ActiveBorder|ActiveCaption|AppWorkspace|Background|ButtonFace|ButtonHighlight|ButtonShadow|ButtonText|CaptionText|GrayText|Highlight|HighlightText|InactiveBorder|InactiveCaption|InactiveCaptionText|InfoBackground|InfoText|Menu|MenuText|Scrollbar|ThreeDDarkShadow|ThreeDFace|ThreeDHighlight|ThreeDLightShadow|ThreeDShadow|Window|WindowFrame|WindowText)|#[0-9a-f]{3}|#[0-9a-f]{6}|rgb\({w}{int}{w},{w}{int}{w},{w}{int}{w}\)|rgb\({w}{num}%{w},{w}{num}%{w},{w}{num}%{w}\)',
|
#'color': r'(maroon|red|orange|yellow|olive|purple|fuchsia|white|lime|green|navy|blue|aqua|teal|black|silver|gray|ActiveBorder|ActiveCaption|AppWorkspace|Background|ButtonFace|ButtonHighlight|ButtonShadow|ButtonText|CaptionText|GrayText|Highlight|HighlightText|InactiveBorder|InactiveCaption|InactiveCaptionText|InfoBackground|InfoText|Menu|MenuText|Scrollbar|ThreeDDarkShadow|ThreeDFace|ThreeDHighlight|ThreeDLightShadow|ThreeDShadow|Window|WindowFrame|WindowText)|#[0-9a-f]{3}|#[0-9a-f]{6}|rgb\({w}{int}{w},{w}{int}{w},{w}{int}{w}\)|rgb\({w}{num}%{w},{w}{num}%{w},{w}{num}%{w}\)',
|
||||||
'integer': r'{int}',
|
'integer': r'{int}',
|
||||||
'length': r'0|{num}(em|ex|px|in|cm|mm|pt|pc)',
|
'length': r'0|{num}(em|ex|px|in|cm|mm|pt|pc)',
|
||||||
|
'positivelength': r'0|{positivenum}(em|ex|px|in|cm|mm|pt|pc)',
|
||||||
'angle': r'0|{num}(deg|grad|rad)',
|
'angle': r'0|{num}(deg|grad|rad)',
|
||||||
'time': r'0|{num}m?s',
|
'time': r'0|{num}m?s',
|
||||||
'frequency': r'0|{num}k?Hz',
|
'frequency': r'0|{num}k?Hz',
|
||||||
@ -97,6 +101,16 @@ class Profiles(object):
|
|||||||
self.addProfile(self.CSS3_COLOR,
|
self.addProfile(self.CSS3_COLOR,
|
||||||
properties[self.CSS3_COLOR],
|
properties[self.CSS3_COLOR],
|
||||||
macros[self.CSS3_COLOR])
|
macros[self.CSS3_COLOR])
|
||||||
|
|
||||||
|
self.addProfile(self.CSS3_FONTS,
|
||||||
|
properties[self.CSS3_FONTS],
|
||||||
|
macros[self.CSS3_FONTS])
|
||||||
|
|
||||||
|
# new object for font-face only?
|
||||||
|
self.addProfile(self.CSS3_FONT_FACE,
|
||||||
|
properties[self.CSS3_FONT_FACE],
|
||||||
|
macros[self.CSS3_FONTS]) # same
|
||||||
|
|
||||||
self.addProfile(self.CSS3_PAGED_MEDIA,
|
self.addProfile(self.CSS3_PAGED_MEDIA,
|
||||||
properties[self.CSS3_PAGED_MEDIA],
|
properties[self.CSS3_PAGED_MEDIA],
|
||||||
macros[self.CSS3_PAGED_MEDIA])
|
macros[self.CSS3_PAGED_MEDIA])
|
||||||
@ -132,7 +146,7 @@ class Profiles(object):
|
|||||||
def _getDefaultProfiles(self):
|
def _getDefaultProfiles(self):
|
||||||
"If not explicitly set same as Profiles.profiles but in reverse order."
|
"If not explicitly set same as Profiles.profiles but in reverse order."
|
||||||
if not self._defaultProfiles:
|
if not self._defaultProfiles:
|
||||||
return self.profiles#list(reversed(self.profiles))
|
return self.profiles
|
||||||
else:
|
else:
|
||||||
return self._defaultProfiles
|
return self._defaultProfiles
|
||||||
|
|
||||||
@ -338,12 +352,12 @@ macros[Profiles.CSS_LEVEL_2] = {
|
|||||||
'shape': r'rect\(({w}({length}|auto}){w},){3}{w}({length}|auto){w}\)',
|
'shape': r'rect\(({w}({length}|auto}){w},){3}{w}({length}|auto){w}\)',
|
||||||
'counter': r'counter\({w}{identifier}{w}(?:,{w}{list-style-type}{w})?\)',
|
'counter': r'counter\({w}{identifier}{w}(?:,{w}{list-style-type}{w})?\)',
|
||||||
'identifier': r'{ident}',
|
'identifier': r'{ident}',
|
||||||
'family-name': r'{string}|{identifier}',
|
'family-name': r'{string}|{identifier}({w}{identifier})*',
|
||||||
'generic-family': r'serif|sans-serif|cursive|fantasy|monospace',
|
'generic-family': r'serif|sans-serif|cursive|fantasy|monospace',
|
||||||
'absolute-size': r'(x?x-)?(small|large)|medium',
|
'absolute-size': r'(x?x-)?(small|large)|medium',
|
||||||
'relative-size': r'smaller|larger',
|
'relative-size': r'smaller|larger',
|
||||||
'font-family': r'(({family-name}|{generic-family}){w},{w})*({family-name}|{generic-family})|inherit',
|
'font-family': r'(({family-name}|{generic-family}){w},{w})*({family-name}|{generic-family})|inherit',
|
||||||
'font-size': r'{absolute-size}|{relative-size}|{length}|{percentage}|inherit',
|
'font-size': r'{absolute-size}|{relative-size}|{positivelength}|{percentage}|inherit',
|
||||||
'font-style': r'normal|italic|oblique|inherit',
|
'font-style': r'normal|italic|oblique|inherit',
|
||||||
'font-variant': r'normal|small-caps|inherit',
|
'font-variant': r'normal|small-caps|inherit',
|
||||||
'font-weight': r'normal|bold|bolder|lighter|[1-9]00|inherit',
|
'font-weight': r'normal|bold|bolder|lighter|[1-9]00|inherit',
|
||||||
@ -495,7 +509,7 @@ macros[Profiles.CSS3_BOX] = {
|
|||||||
'overflow': macros[Profiles.CSS_LEVEL_2]['overflow']
|
'overflow': macros[Profiles.CSS_LEVEL_2]['overflow']
|
||||||
}
|
}
|
||||||
properties[Profiles.CSS3_BOX] = {
|
properties[Profiles.CSS3_BOX] = {
|
||||||
'overflow': '{overflow}\s?{overflow}?|inherit',
|
'overflow': '{overflow}{w}{overflow}?|inherit',
|
||||||
'overflow-x': '{overflow}|inherit',
|
'overflow-x': '{overflow}|inherit',
|
||||||
'overflow-y': '{overflow}|inherit'
|
'overflow-y': '{overflow}|inherit'
|
||||||
}
|
}
|
||||||
@ -515,6 +529,28 @@ properties[Profiles.CSS3_COLOR] = {
|
|||||||
'opacity': r'{num}|inherit'
|
'opacity': r'{num}|inherit'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# CSS Fonts Module Level 3 http://www.w3.org/TR/css3-fonts/
|
||||||
|
macros[Profiles.CSS3_FONTS] = {
|
||||||
|
'family-name': r'{string}|{ident}', # but STRING is effectively an IDENT???
|
||||||
|
'font-face-name': 'local\({w}{ident}{w}\)',
|
||||||
|
'font-stretch-names': r'(ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded)',
|
||||||
|
'unicode-range': r'[uU]\+[0-9A-Fa-f?]{1,6}(\-[0-9A-Fa-f]{1,6})?'
|
||||||
|
}
|
||||||
|
properties[Profiles.CSS3_FONTS] = {
|
||||||
|
'font-size-adjust': r'{number}|none|inherit',
|
||||||
|
'font-stretch': r'normal|wider|narrower|{font-stretch-names}|inherit'
|
||||||
|
}
|
||||||
|
properties[Profiles.CSS3_FONT_FACE] = {
|
||||||
|
'font-family': '{family-name}',
|
||||||
|
'font-stretch': r'{font-stretch-names}',
|
||||||
|
'font-style': r'normal|italic|oblique',
|
||||||
|
'font-weight': r'normal|bold|[1-9]00',
|
||||||
|
'src': r'({uri}{w}(format\({w}{string}{w}(\,{w}{string}{w})*\))?|{font-face-name})({w},{w}({uri}{w}(format\({w}{string}{w}(\,{w}{string}{w})*\))?|{font-face-name}))*',
|
||||||
|
'unicode-range': '{unicode-range}({w},{w}{unicode-range})*'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# CSS3 Paged Media
|
# CSS3 Paged Media
|
||||||
macros[Profiles.CSS3_PAGED_MEDIA] = {
|
macros[Profiles.CSS3_PAGED_MEDIA] = {
|
||||||
'pagesize': 'a5|a4|a3|b5|b4|letter|legal|ledger',
|
'pagesize': 'a5|a4|a3|b5|b4|letter|legal|ledger',
|
||||||
|
13
src/cssutils/settings.py
Normal file
13
src/cssutils/settings.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
"""Experimental settings for special stuff."""
|
||||||
|
|
||||||
|
def set(key, value):
|
||||||
|
"""Call to enable special settings:
|
||||||
|
|
||||||
|
('DXImageTransform.Microsoft', True)
|
||||||
|
enable support for parsing special MS only filter values
|
||||||
|
|
||||||
|
"""
|
||||||
|
if key == 'DXImageTransform.Microsoft' and value == True:
|
||||||
|
import cssproductions
|
||||||
|
cssproductions.PRODUCTIONS.insert(1, cssproductions._DXImageTransform)
|
||||||
|
|
@ -4,7 +4,7 @@
|
|||||||
"""
|
"""
|
||||||
__all__ = ['Tokenizer', 'CSSProductions']
|
__all__ = ['Tokenizer', 'CSSProductions']
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: tokenize2.py 1547 2008-12-10 20:42:26Z cthedot $'
|
__version__ = '$Id: tokenize2.py 1834 2009-08-02 12:20:21Z cthedot $'
|
||||||
|
|
||||||
from cssproductions import *
|
from cssproductions import *
|
||||||
from helper import normalize
|
from helper import normalize
|
||||||
@ -147,7 +147,8 @@ class Tokenizer(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if name in ('DIMENSION', 'IDENT', 'STRING', 'URI',
|
if name in ('DIMENSION', 'IDENT', 'STRING', 'URI',
|
||||||
'HASH', 'COMMENT', 'FUNCTION', 'INVALID'):
|
'HASH', 'COMMENT', 'FUNCTION', 'INVALID',
|
||||||
|
'UNICODE-RANGE'):
|
||||||
# may contain unicode escape, replace with normal char
|
# may contain unicode escape, replace with normal char
|
||||||
# but do not _normalize (?)
|
# but do not _normalize (?)
|
||||||
value = self.unicodesub(_repl, found)
|
value = self.unicodesub(_repl, found)
|
||||||
@ -166,7 +167,6 @@ class Tokenizer(object):
|
|||||||
name = self._atkeywords.get(_normalize(found), 'ATKEYWORD')
|
name = self._atkeywords.get(_normalize(found), 'ATKEYWORD')
|
||||||
|
|
||||||
value = found # should not contain unicode escape (?)
|
value = found # should not contain unicode escape (?)
|
||||||
|
|
||||||
yield (name, value, line, col)
|
yield (name, value, line, col)
|
||||||
text = text[len(found):]
|
text = text[len(found):]
|
||||||
nls = found.count(self._linesep)
|
nls = found.count(self._linesep)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"""
|
"""
|
||||||
__all__ = []
|
__all__ = []
|
||||||
__docformat__ = 'restructuredtext'
|
__docformat__ = 'restructuredtext'
|
||||||
__version__ = '$Id: util.py 1743 2009-05-09 20:33:15Z cthedot $'
|
__version__ = '$Id: util.py 1781 2009-07-19 12:30:49Z cthedot $'
|
||||||
|
|
||||||
from helper import normalize
|
from helper import normalize
|
||||||
from itertools import ifilter
|
from itertools import ifilter
|
||||||
@ -663,6 +663,9 @@ class _Namespaces(object):
|
|||||||
self.parentStyleSheet = parentStyleSheet
|
self.parentStyleSheet = parentStyleSheet
|
||||||
self._log = log
|
self._log = log
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "%r" % self.namespaces
|
||||||
|
|
||||||
def __contains__(self, prefix):
|
def __contains__(self, prefix):
|
||||||
return prefix in self.namespaces
|
return prefix in self.namespaces
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user