frappe/env/lib/python3.12/site-packages/cssutils/stylesheets/mediaquery.py

235 lines
6.9 KiB
Python

"""Implements a DOM for MediaQuery, see
http://www.w3.org/TR/css3-mediaqueries/.
A cssutils implementation, not defined in official DOM.
"""
__all__ = ['MediaQuery']
from cssutils.prodparser import Choice, PreDef, Prod, ProdParser, Sequence
from cssutils.helper import normalize
import cssutils
import xml.dom
class MediaQuery(cssutils.util._NewBase): # cssutils.util.Base):
"""
A Media Query consists of one of ``MediaQuery.MEDIA_TYPES``
and one or more expressions involving media features.
Format::
media_query
: [ONLY | NOT]? S* media_type S* [ AND S* expression ]*
| expression [ AND S* expression ]*
;
media_type
: IDENT
;
expression
: '(' S* media_feature S* [ ':' S* expr ]? ')' S*
;
media_feature
: IDENT
;
"""
MEDIA_TYPES = [
'all',
'braille',
'handheld',
'print',
'projection',
'speech',
'screen',
'tty',
'tv',
'embossed',
]
def __init__(self, mediaText=None, readonly=False, _partof=False):
"""
:param mediaText:
unicodestring of parsable media
# _standalone: True if new from ML parser
"""
super().__init__()
self._wellformed = False
self._mediaType = ''
self._partof = _partof
if mediaText:
self.mediaText = mediaText # sets self._mediaType too
self._partof = False
self._readonly = readonly
def __repr__(self):
return "cssutils.stylesheets.{}(mediaText={!r})".format(
self.__class__.__name__,
self.mediaText,
)
def __str__(self):
return "<cssutils.stylesheets.{} object mediaText={!r} at 0x{:x}>".format(
self.__class__.__name__,
self.mediaText,
id(self),
)
def _getMediaText(self):
return cssutils.ser.do_stylesheets_mediaquery(self)
def _setMediaText(self, mediaText):
"""
:param mediaText:
a single media query string, e.g. ``print and (min-width: 25cm)``
:exceptions:
- :exc:`~xml.dom.SyntaxErr`:
Raised if the specified string value has a syntax error and is
unparsable.
- :exc:`~xml.dom.InvalidCharacterErr`:
Raised if the given mediaType is unknown.
- :exc:`~xml.dom.NoModificationAllowedErr`:
Raised if this media query is readonly.
media_query
: [ONLY | NOT]? S* media_type S* [ AND S* expression ]*
| expression [ AND S* expression ]*
;
media_type
: IDENT
;
expression
: '(' S* media_feature S* [ ':' S* expr ]? ')' S*
;
media_feature
: IDENT
;
"""
self._checkReadonly()
expression = lambda: Sequence( # noqa
PreDef.char(name='expression', char='('),
Prod(name='media_feature', match=lambda t, v: t == PreDef.types.IDENT),
Sequence(
PreDef.char(name='colon', char=':'),
cssutils.css.value.MediaQueryValueProd(self),
minmax=lambda: (0, 1), # optional
),
PreDef.char(
name='expression END', char=')', stopIfNoMoreMatch=self._partof
),
)
prods = Choice(
Sequence(
Prod(
name='ONLY|NOT', # media_query
match=lambda t, v: t == PreDef.types.IDENT
and normalize(v) in ('only', 'not'),
optional=True,
toStore='not simple',
),
Prod(
name='media_type',
match=lambda t, v: t == PreDef.types.IDENT
and normalize(v) in self.MEDIA_TYPES,
stopIfNoMoreMatch=True,
toStore='media_type',
),
Sequence(
Prod(
name='AND',
match=lambda t, v: t == PreDef.types.IDENT
and normalize(v) == 'and',
toStore='not simple',
),
expression(),
minmax=lambda: (0, None),
),
),
Sequence(
expression(),
Sequence(
Prod(
name='AND',
match=lambda t, v: t == PreDef.types.IDENT
and normalize(v) == 'and',
),
expression(),
minmax=lambda: (0, None),
),
),
)
# parse
ok, seq, store, unused = ProdParser().parse(mediaText, 'MediaQuery', prods)
self._wellformed = ok
if ok:
try:
media_type = store['media_type']
except KeyError:
pass
else:
if 'not simple' not in store:
self.mediaType = media_type.value
# TODO: filter doubles!
self._setSeq(seq)
mediaText = property(
_getMediaText,
_setMediaText,
doc="The parsable textual representation of the media list.",
)
def _setMediaType(self, mediaType):
"""
:param mediaType:
one of :attr:`MEDIA_TYPES`
:exceptions:
- :exc:`~xml.dom.SyntaxErr`:
Raised if the specified string value has a syntax error and is
unparsable.
- :exc:`~xml.dom.InvalidCharacterErr`:
Raised if the given mediaType is unknown.
- :exc:`~xml.dom.NoModificationAllowedErr`:
Raised if this media query is readonly.
"""
self._checkReadonly()
nmediaType = normalize(mediaType)
if nmediaType not in self.MEDIA_TYPES:
self._log.error(
'MediaQuery: Syntax Error in media type "%s".' % mediaType,
error=xml.dom.SyntaxErr,
)
else:
# set
self._mediaType = mediaType
# update seq
for i, x in enumerate(self._seq):
if isinstance(x.value, str):
if normalize(x.value) in ('only', 'not'):
continue
else:
# TODO: simplify!
self._seq[i] = (mediaType, 'IDENT', None, None)
break
else:
self._seq.insert(0, mediaType, 'IDENT')
mediaType = property(
lambda self: self._mediaType,
_setMediaType,
doc="The media type of this MediaQuery (one of "
"``MEDIA_TYPES``) but only if it is a simple MediaType!",
)
wellformed = property(lambda self: self._wellformed)