2
MediaQuery, see http://www.w3.org/TR/css3-mediaqueries/
4
A cssutils own implementation, not defined in official DOM
9
part of a media_query_list: <media_query> [, <media_query> ]*
10
see stylesheets.MediaList
12
__all__ = ['MediaQuery']
13
__docformat__ = 'restructuredtext'
14
__version__ = '$Id: mediaquery.py 1363 2008-07-13 18:14:26Z cthedot $'
20
class MediaQuery(cssutils.util.Base):
22
A Media Query consists of a media type and one or more
23
expressions involving media features.
27
mediaText: of type DOMString
28
The parsable textual representation of this MediaQuery
29
mediaType: of type DOMString
30
one of MEDIA_TYPES like e.g. 'print'
31
seq: a list (cssutils)
32
All parts of this MediaQuery including CSSComments
34
if this query is wellformed
40
media_query: [[only | not]? <media_type> [ and <expression> ]*]
41
| <expression> [ and <expression> ]*
42
expression: ( <media_feature> [: <value>]? )
43
media_type: all | aural | braille | handheld | print |
44
projection | screen | tty | tv | embossed
45
media_feature: width | min-width | max-width
46
| height | min-height | max-height
47
| device-width | min-device-width | max-device-width
48
| device-height | min-device-height | max-device-height
49
| device-aspect-ratio | min-device-aspect-ratio | max-device-aspect-ratio
50
| color | min-color | max-color
51
| color-index | min-color-index | max-color-index
52
| monochrome | min-monochrome | max-monochrome
53
| resolution | min-resolution | max-resolution
57
MEDIA_TYPES = [u'all', u'aural', u'braille', u'embossed', u'handheld',
58
u'print', u'projection', u'screen', u'tty', u'tv']
60
# From the HTML spec (see MediaQuery):
61
# "[...] character that isn't a US ASCII letter [a-zA-Z] (Unicode
62
# decimal 65-90, 97-122), digit [0-9] (Unicode hex 30-39), or hyphen (45)."
63
# so the following is a valid mediaType
64
__mediaTypeMatch = re.compile(ur'^[-a-zA-Z0-9]+$', re.U).match
66
def __init__(self, mediaText=None, readonly=False):
69
unicodestring of parsable media
71
super(MediaQuery, self).__init__()
76
self.mediaText = mediaText # sets self._mediaType too
78
self._readonly = readonly
80
def _getMediaText(self):
82
returns serialized property mediaText
84
return cssutils.ser.do_stylesheets_mediaquery(self)
86
def _setMediaText(self, mediaText):
89
a single media query string, e.g. "print and (min-width: 25cm)"
94
Raised if the specified string value has a syntax error and is
96
- INVALID_CHARACTER_ERR: (self)
97
Raised if the given mediaType is unknown.
98
- NO_MODIFICATION_ALLOWED_ERR: (self)
99
Raised if this media query is readonly.
101
self._checkReadonly()
102
tokenizer = self._tokenize2(mediaText)
104
self._log.error(u'MediaQuery: No MediaText given.')
106
# for closures: must be a mutable
107
new = {'mediatype': None,
110
def _ident_or_dim(expected, seq, token, tokenizer=None):
111
# only|not or mediatype or and
112
val = self._tokenvalue(token)
113
nval = self._normalize(val)
114
if expected.endswith('mediatype'):
115
if nval in (u'only', u'not'):
121
new['mediatype'] = val
124
elif 'and' == nval and expected.startswith('and'):
128
new['wellformed'] = False
130
u'MediaQuery: Unexpected syntax.', token=token)
133
def _char(expected, seq, token, tokenizer=None):
134
# starting a feature which basically is a CSS Property
135
# but may simply be a property name too
136
val = self._tokenvalue(token)
137
if val == u'(' and expected == 'feature':
138
proptokens = self._tokensupto2(
139
tokenizer, funcendonly=True)
140
if proptokens and u')' == self._tokenvalue(proptokens[-1]):
142
property = cssutils.css.Property(_mediaQuery=True)
143
property.cssText = proptokens
147
new['wellformed'] = False
149
u'MediaQuery: Unexpected syntax, expected "and" but found "%s".' %
153
# expected: only|not or mediatype, mediatype, feature, and
155
wellformed, expected = self._parse(expected='only|not or mediatype',
156
seq=newseq, tokenizer=tokenizer,
157
productions={'IDENT': _ident_or_dim, # e.g. "print"
158
'DIMENSION': _ident_or_dim, # e.g. "3d"
160
wellformed = wellformed and new['wellformed']
163
if not new['mediatype']:
165
self._log.error(u'MediaQuery: No mediatype found: %s' %
166
self._valuestr(mediaText))
170
self.mediaType = new['mediatype']
173
mediaText = property(_getMediaText, _setMediaText,
174
doc="""(DOM) The parsable textual representation of the media list.
175
This is a comma-separated list of media.""")
177
def _getMediaType(self):
179
returns serialized property mediaText
181
return self._mediaType
183
def _setMediaType(self, mediaType):
191
Raised if the specified string value has a syntax error and is
193
- INVALID_CHARACTER_ERR: (self)
194
Raised if the given mediaType is unknown.
195
- NO_MODIFICATION_ALLOWED_ERR: (self)
196
Raised if this media query is readonly.
198
self._checkReadonly()
199
nmediaType = self._normalize(mediaType)
201
if not MediaQuery.__mediaTypeMatch(nmediaType):
203
u'MediaQuery: Syntax Error in media type "%s".' % mediaType,
204
error=xml.dom.SyntaxErr)
206
if nmediaType not in MediaQuery.MEDIA_TYPES:
208
u'MediaQuery: Unknown media type "%s".' % mediaType,
209
error=xml.dom.InvalidCharacterErr)
213
self._mediaType = mediaType
216
for i, x in enumerate(self.seq):
217
if isinstance(x, basestring):
218
if self._normalize(x) in (u'only', u'not'):
221
self.seq[i] = mediaType
224
self.seq.insert(0, mediaType)
226
mediaType = property(_getMediaType, _setMediaType,
227
doc="""(DOM) media type (one of MediaQuery.MEDIA_TYPES) of this MediaQuery.""")
229
wellformed = property(lambda self: bool(len(self.seq)))
232
return "cssutils.stylesheets.%s(mediaText=%r)" % (
233
self.__class__.__name__, self.mediaText)
236
return "<cssutils.stylesheets.%s object mediaText=%r at 0x%x>" % (
237
self.__class__.__name__, self.mediaText, id(self))