def setVariable(self, variableName, value):
        """Used to set a variable value within this variable declaration block.

        :param variableName:
            The name of the CSS variable.
        :param value:
            The new value of the variable, may also be a PropertyValue object.

        :exceptions:
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified value has a syntax error and is
              unparsable.
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this declaration is readonly or the property is
              readonly.
        """
        self._checkReadonly()

        # check name
        wellformed, seq, store, unused = \
            ProdParser().parse(normalize(variableName),
                               'variableName',
                               Sequence(PreDef.ident()))
        if not wellformed:
            self._log.error('Invalid variableName: %r: %r'
                            % (variableName, value))
        else:
            # check value
            if isinstance(value, PropertyValue):
                v = value
            else:
                v = PropertyValue(cssText=value, parent=self)

            if not v.wellformed:
                self._log.error('Invalid variable value: %r: %r'
                                % (variableName, value))
            else:
                # update seq
                self.seq._readonly = False

                variableName = normalize(variableName)

                if variableName in self._vars:
                    for i, x in enumerate(self.seq):
                        if x.value[0] == variableName:
                            self.seq.replace(i,
                                             [variableName, v],
                                             x.type,
                                             x.line,
                                             x.col)
                            break
                else:
                    self.seq.append([variableName, v], 'var')
                self.seq._readonly = True
                self._vars[variableName] = v
Esempio n. 2
0
def _ColorProd(parent, nextSor=False, toStore=None):
    return Prod(
        name='ColorValue',
        match=lambda t, v: (t == 'HASH' and reHexcolor.match(v)) or
        (t == 'FUNCTION' and normalize(v) in
         ('rgb(', 'rgba(', 'hsl(', 'hsla(')) or
        (t == 'IDENT' and normalize(v) in as_list(ColorValue.COLORS.keys())),
        nextSor=nextSor,
        toStore=toStore,
        toSeq=lambda t, tokens:
        ('ColorValue', ColorValue(pushtoken(t, tokens), parent=parent)))
Esempio n. 3
0
    def setVariable(self, variableName, value):
        """Used to set a variable value within this variable declaration block.

        :param variableName:
            The name of the CSS variable.
        :param value:
            The new value of the variable, may also be a PropertyValue object.

        :exceptions:
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified value has a syntax error and is
              unparsable.
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this declaration is readonly or the property is
              readonly.
        """
        self._checkReadonly()

        # check name
        wellformed, seq, store, unused = \
            ProdParser().parse(normalize(variableName),
                               'variableName',
                               Sequence(PreDef.ident()))
        if not wellformed:
            self._log.error('Invalid variableName: %r: %r' %
                            (variableName, value))
        else:
            # check value
            if isinstance(value, PropertyValue):
                v = value
            else:
                v = PropertyValue(cssText=value, parent=self)

            if not v.wellformed:
                self._log.error('Invalid variable value: %r: %r' %
                                (variableName, value))
            else:
                # update seq
                self.seq._readonly = False

                variableName = normalize(variableName)

                if variableName in self._vars:
                    for i, x in enumerate(self.seq):
                        if x.value[0] == variableName:
                            self.seq.replace(i, [variableName, v], x.type,
                                             x.line, x.col)
                            break
                else:
                    self.seq.append([variableName, v], 'var')
                self.seq._readonly = True
                self._vars[variableName] = v
Esempio n. 4
0
    def appendMedium(self, newMedium):
        """Add the `newMedium` to the end of the list.
        If the `newMedium` is already used, it is first removed.

        :param newMedium:
            a string or a :class:`~css_parser.stylesheets.MediaQuery`
        :returns: Wellformedness of `newMedium`.
        :exceptions:
            - :exc:`~xml.dom.InvalidCharacterErr`:
              If the medium contains characters that are invalid in the
              underlying style language.
            - :exc:`~xml.dom.InvalidModificationErr`:
              If mediaText is "all" and a new medium is tried to be added.
              Exception is "handheld" which is set in any case (Opera does handle
              "all, handheld" special, this special case might be removed in the
              future).
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this list is readonly.
        """
        newMedium = self.__prepareset(newMedium)

        if newMedium:
            mts = [normalize(item.value.mediaType) for item in self]
            newmt = normalize(newMedium.mediaType)

            self._seq._readonly = False

            if 'all' in mts:
                self._log.info(
                    'MediaList: Ignoring new medium %r as already specified "all" (set ``mediaText`` instead).'
                    % newMedium,
                    error=xml.dom.InvalidModificationErr)

            elif newmt and newmt in mts:
                # might be empty
                self.deleteMedium(newmt)
                self._seq.append(newMedium, 'MediaQuery')

            else:
                if 'all' == newmt:
                    self._clearSeq()

                self._seq.append(newMedium, 'MediaQuery')

            self._seq._readonly = True

            return True

        else:
            return False
Esempio n. 5
0
    def appendMedium(self, newMedium):
        """Add the `newMedium` to the end of the list.
        If the `newMedium` is already used, it is first removed.

        :param newMedium:
            a string or a :class:`~css_parser.stylesheets.MediaQuery`
        :returns: Wellformedness of `newMedium`.
        :exceptions:
            - :exc:`~xml.dom.InvalidCharacterErr`:
              If the medium contains characters that are invalid in the
              underlying style language.
            - :exc:`~xml.dom.InvalidModificationErr`:
              If mediaText is "all" and a new medium is tried to be added.
              Exception is "handheld" which is set in any case (Opera does handle
              "all, handheld" special, this special case might be removed in the
              future).
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this list is readonly.
        """
        newMedium = self.__prepareset(newMedium)

        if newMedium:
            mts = [normalize(item.value.mediaType) for item in self]
            newmt = normalize(newMedium.mediaType)

            self._seq._readonly = False

            if 'all' in mts:
                self._log.info(
                    'MediaList: Ignoring new medium %r as already specified "all" (set ``mediaText`` instead).' %
                    newMedium, error=xml.dom.InvalidModificationErr)

            elif newmt and newmt in mts:
                # might be empty
                self.deleteMedium(newmt)
                self._seq.append(newMedium, 'MediaQuery')

            else:
                if 'all' == newmt:
                    self._clearSeq()

                self._seq.append(newMedium, 'MediaQuery')

            self._seq._readonly = True

            return True

        else:
            return False
Esempio n. 6
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        prods = Sequence(  # PreDef.unary(),
            Choice(PreDef.dimension(stop=True), PreDef.number(stop=True),
                   PreDef.percentage(stop=True)))
        ok, seq, store, unused = ProdParser().parse(cssText, 'DimensionValue',
                                                    prods)
        self.wellformed = ok
        if ok:
            item = seq[0]

            sign, v, d = self.__reUnNumDim.findall(normalize(item.value))[0]
            if '.' in v:
                val = float(sign + v)
            else:
                val = int(sign + v)

            dim = None
            if d:
                dim = d

            self._sign = sign
            self._value = val
            self._dimension = dim
            self._type = item.type

            self._setSeq(seq)
Esempio n. 7
0
def _MSValueProd(parent, nextSor=False):
    return Prod(name=MSValue._functionName,
                match=lambda t, v: (  # t == self._prods.FUNCTION and (
                    normalize(v) in ('expression(',
                                     'alpha(',
                                     'blur(',
                                     'chroma(',
                                     'dropshadow(',
                                     'fliph(',
                                     'flipv(',
                                     'glow(',
                                     'gray(',
                                     'invert(',
                                     'mask(',
                                     'shadow(',
                                     'wave(',
                                     'xray(') or
                    v.startswith('progid:DXImageTransform.Microsoft.')
                ),
                nextSor=nextSor,
                toSeq=lambda t, tokens: (MSValue._functionName,
                                         MSValue(pushtoken(t,
                                                           tokens
                                                           ),
                                                 parent=parent
                                                 )
                                         )
                )
Esempio n. 8
0
def _MSValueProd(parent, nextSor=False):
    return Prod(name=MSValue._functionName,
                match=lambda t, v: (  # t == self._prods.FUNCTION and (
                    normalize(v) in ('expression(',
                                     'alpha(',
                                     'blur(',
                                     'chroma(',
                                     'dropshadow(',
                                     'fliph(',
                                     'flipv(',
                                     'glow(',
                                     'gray(',
                                     'invert(',
                                     'mask(',
                                     'shadow(',
                                     'wave(',
                                     'xray(') or
                    v.startswith('progid:DXImageTransform.Microsoft.')
                ),
                nextSor=nextSor,
                toSeq=lambda t, tokens: (MSValue._functionName,
                                         MSValue(pushtoken(t,
                                                           tokens
                                                           ),
                                                 parent=parent
                                                 )
                                         )
                )
Esempio n. 9
0
    def __contains__(self, variableName):
        """Check if a variable is in variable declaration block.

        :param variableName:
            a string
        """
        return normalize(variableName) in as_list(self.keys())
Esempio n. 10
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods  # rename!
        prods = Sequence(
            Prod(name='var',
                 match=lambda t, v: t == types.FUNCTION and normalize(v) ==
                 'var('), PreDef.ident(toStore='ident'),
            Sequence(PreDef.comma(),
                     Choice(_ColorProd(self, toStore='fallback'),
                            _DimensionProd(self, toStore='fallback'),
                            _URIProd(self, toStore='fallback'),
                            _ValueProd(self, toStore='fallback'),
                            _CalcValueProd(self, toStore='fallback'),
                            _CSSVariableProd(self, toStore='fallback'),
                            _CSSFunctionProd(self, toStore='fallback')),
                     minmax=lambda: (0, 1)), PreDef.funcEnd(stop=True))

        # store: name of variable
        store = {'ident': None, 'fallback': None}
        ok, seq, store, unused = ProdParser().parse(cssText, 'CSSVariable',
                                                    prods)
        self.wellformed = ok

        if ok:
            self._name = store['ident'].value
            try:
                self._fallback = store['fallback'].value
            except KeyError:
                self._fallback = None

            self._setSeq(seq)
Esempio n. 11
0
    def __contains__(self, variableName):
        """Check if a variable is in variable declaration block.

        :param variableName:
            a string
        """
        return normalize(variableName) in as_list(self.keys())
Esempio n. 12
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        prods = Sequence(  # PreDef.unary(),
            Choice(PreDef.dimension(stop=True),
                   PreDef.number(stop=True),
                   PreDef.percentage(stop=True)
                   )
        )
        ok, seq, store, unused = ProdParser().parse(cssText,
                                                    'DimensionValue',
                                                    prods)
        self.wellformed = ok
        if ok:
            item = seq[0]

            sign, v, d = self.__reUnNumDim.findall(
                normalize(item.value))[0]
            if '.' in v:
                val = float(sign + v)
            else:
                val = int(sign + v)

            dim = None
            if d:
                dim = d

            self._sign = sign
            self._value = val
            self._dimension = dim
            self._type = item.type

            self._setSeq(seq)
Esempio n. 13
0
    def do_css_CSSVariablesDeclaration(self, variables):
        """Variables of CSSVariableRule."""
        if len(variables.seq) > 0:
            out = Out(self)

            lastitem = len(variables.seq) - 1
            for i, item in enumerate(variables.seq):
                type_, val = item.type, item.value
                if 'var' == type_:
                    name, cssvalue = val
                    if self.prefs.normalizedVarNames:
                        name = normalize(name)
                    out.append(name)
                    out.append(':')
                    out.append(cssvalue.cssText)
                    if i < lastitem or not self.prefs.omitLastSemicolon:
                        out.append(';')

                elif isinstance(val, css_parser.css.CSSComment):
                    # CSSComment
                    out.append(val, 'COMMENT')
                    out.append(self.prefs.lineSeparator)
                else:
                    out.append(val.cssText, type_)
                    out.append(self.prefs.lineSeparator)

            return out.value().strip()

        else:
            return ''
Esempio n. 14
0
    def do_css_CSSVariablesDeclaration(self, variables):
        """Variables of CSSVariableRule."""
        if len(variables.seq) > 0:
            out = Out(self)

            lastitem = len(variables.seq) - 1
            for i, item in enumerate(variables.seq):
                type_, val = item.type, item.value
                if 'var' == type_:
                    name, cssvalue = val
                    if self.prefs.normalizedVarNames:
                        name = normalize(name)
                    out.append(name)
                    out.append(':')
                    out.append(cssvalue.cssText)
                    if i < lastitem or not self.prefs.omitLastSemicolon:
                        out.append(';')

                elif isinstance(val, css_parser.css.CSSComment):
                    # CSSComment
                    out.append(val, 'COMMENT')
                    out.append(self.prefs.lineSeparator)
                else:
                    out.append(val.cssText, type_)
                    out.append(self.prefs.lineSeparator)

            return out.value().strip()

        else:
            return ''
Esempio n. 15
0
def _CalcValueProd(parent, nextSor=False, toStore=None):
    return Prod(
        name=CSSCalc._functionName,
        match=lambda t, v: t == PreDef.types.FUNCTION and normalize(
            v) == 'calc(',
        toStore=toStore,
        toSeq=lambda t, tokens:
        (CSSCalc._functionName, CSSCalc(pushtoken(t, tokens), parent=parent)),
        nextSor=nextSor)
Esempio n. 16
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods  # rename!

        _operator = Choice(Prod(name='Operator */',
                                match=lambda t, v: v in '*/',
                                toSeq=lambda t, tokens: (t[0], t[1])
                                ),
                           Sequence(
                               PreDef.S(),
                               Choice(
                                   Sequence(
                                       Prod(name='Operator */',
                                            match=lambda t, v: v in '*/',
                                            toSeq=lambda t, tokens: (t[0], t[1])
                                            ),
                                       PreDef.S(optional=True)
                                   ),
                                   Sequence(
                                       Prod(name='Operator +-',
                                            match=lambda t, v: v in '+-',
                                            toSeq=lambda t, tokens: (t[0], t[1])
                                            ),
                                       PreDef.S()
                                   ),
                                   PreDef.funcEnd(stop=True, mayEnd=True)
                               )
        )
        )

        def _operant(): return Choice(_DimensionProd(self),
                                      _CSSVariableProd(self))

        prods = Sequence(Prod(name='CALC',
                              match=lambda t, v: t == types.FUNCTION and
                              normalize(v) == 'calc('
                              ),
                         PreDef.S(optional=True),
                         _operant(),
                         Sequence(_operator,
                                  _operant(),
                                  minmax=lambda: (0, None)
                                  ),
                         PreDef.funcEnd(stop=True)
                         )

        # store: name of variable
        ok, seq, store, unused = ProdParser().parse(cssText,
                                                    'CSSCalc',
                                                    prods,
                                                    checkS=True)
        self.wellformed = ok
        if ok:
            self._setSeq(seq)
Esempio n. 17
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods  # rename!

        _operator = Choice(Prod(name='Operator */',
                                match=lambda t, v: v in '*/',
                                toSeq=lambda t, tokens: (t[0], t[1])
                                ),
                           Sequence(
                               PreDef.S(),
                               Choice(
                                   Sequence(
                                       Prod(name='Operator */',
                                            match=lambda t, v: v in '*/',
                                            toSeq=lambda t, tokens: (t[0], t[1])
                                            ),
                                       PreDef.S(optional=True)
                                   ),
                                   Sequence(
                                       Prod(name='Operator +-',
                                            match=lambda t, v: v in '+-',
                                            toSeq=lambda t, tokens: (t[0], t[1])
                                            ),
                                       PreDef.S()
                                   ),
                                   PreDef.funcEnd(stop=True, mayEnd=True)
                               )
        )
        )

        def _operant(): return Choice(_DimensionProd(self),
                                      _CSSVariableProd(self))

        prods = Sequence(Prod(name='CALC',
                              match=lambda t, v: t == types.FUNCTION and
                              normalize(v) == 'calc('
                              ),
                         PreDef.S(optional=True),
                         _operant(),
                         Sequence(_operator,
                                  _operant(),
                                  minmax=lambda: (0, None)
                                  ),
                         PreDef.funcEnd(stop=True)
                         )

        # store: name of variable
        ok, seq, store, unused = ProdParser().parse(cssText,
                                                    'CSSCalc',
                                                    prods,
                                                    checkS=True)
        self.wellformed = ok
        if ok:
            self._setSeq(seq)
Esempio n. 18
0
def _CalcValueProd(parent, nextSor=False, toStore=None):
    return Prod(name=CSSCalc._functionName,
                match=lambda t, v: t == PreDef.types.FUNCTION and
                normalize(v) == 'calc(',
                toStore=toStore,
                toSeq=lambda t, tokens: (CSSCalc._functionName,
                                         CSSCalc(
                                             pushtoken(t, tokens),
                                             parent=parent)
                                         ),
                nextSor=nextSor)
Esempio n. 19
0
    def deleteMedium(self, oldMedium):
        """Delete a medium from the list.

        :param oldMedium:
            delete this medium from the list.
        :exceptions:
            - :exc:`~xml.dom.NotFoundErr`:
              Raised if `oldMedium` is not in the list.
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this list is readonly.
        """
        self._checkReadonly()
        oldMedium = normalize(oldMedium)

        for i, mq in enumerate(self):
            if normalize(mq.value.mediaType) == oldMedium:
                del self[i]
                break
        else:
            self._log.error('"%s" not in this MediaList' % oldMedium,
                            error=xml.dom.NotFoundErr)
Esempio n. 20
0
    def deleteMedium(self, oldMedium):
        """Delete a medium from the list.

        :param oldMedium:
            delete this medium from the list.
        :exceptions:
            - :exc:`~xml.dom.NotFoundErr`:
              Raised if `oldMedium` is not in the list.
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this list is readonly.
        """
        self._checkReadonly()
        oldMedium = normalize(oldMedium)

        for i, mq in enumerate(self):
            if normalize(mq.value.mediaType) == oldMedium:
                del self[i]
                break
        else:
            self._log.error('"%s" not in this MediaList' % oldMedium,
                            error=xml.dom.NotFoundErr)
Esempio n. 21
0
def _ColorProd(parent, nextSor=False, toStore=None):
    return Prod(name='ColorValue',
                match=lambda t, v:
                (t == 'HASH' and
                 reHexcolor.match(v)
                 ) or
                (t == 'FUNCTION' and
                 normalize(v) in ('rgb(',
                                  'rgba(',
                                  'hsl(',
                                  'hsla(')
                 ) or
                (t == 'IDENT' and
                 normalize(v) in as_list(ColorValue.COLORS.keys())
                 ),
                nextSor=nextSor,
                toStore=toStore,
                toSeq=lambda t, tokens: ('ColorValue', ColorValue(
                    pushtoken(t,
                              tokens),
                    parent=parent)
                )
                )
Esempio n. 22
0
    def _setMediaType(self, mediaType):
        """
        :param mediaType:
            usually 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.warn(
                'MediaQuery: Unknown media type: "%s".' % mediaType,
                error=UnknownMediaType, neverraise=True)

        # set
        self._mediaType = mediaType

        # update seq
        for i, x in enumerate(self._seq):
            if isinstance(x.value, string_type):
                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')
Esempio n. 23
0
    def _setMediaType(self, mediaType):
        """
        :param mediaType:
            usually 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.warn('MediaQuery: Unknown media type: "%s".' % mediaType,
                           error=UnknownMediaType,
                           neverraise=True)

        # set
        self._mediaType = mediaType

        # update seq
        for i, x in enumerate(self._seq):
            if isinstance(x.value, string_type):
                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')
Esempio n. 24
0
    def getVariableValue(self, variableName):
        """Used to retrieve the value of a variable if it has been explicitly
        set within this variable declaration block.

        :param variableName:
            The name of the variable.
        :returns:
            the value of the variable if it has been explicitly set in this
            variable declaration block. Returns the empty string if the
            variable has not been set.
        """
        try:
            return self._vars[normalize(variableName)].cssText
        except KeyError:
            return ''
Esempio n. 25
0
    def getVariableValue(self, variableName):
        """Used to retrieve the value of a variable if it has been explicitly
        set within this variable declaration block.

        :param variableName:
            The name of the variable.
        :returns:
            the value of the variable if it has been explicitly set in this
            variable declaration block. Returns the empty string if the
            variable has not been set.
        """
        try:
            return self._vars[normalize(variableName)].cssText
        except KeyError:
            return ''
Esempio n. 26
0
    def _productions(self):
        """Return definition used for parsing."""
        types = self._prods  # rename!

        itemProd = Choice(_ColorProd(self), _DimensionProd(self),
                          _URIProd(self), _ValueProd(self),
                          _CalcValueProd(self), _CSSVariableProd(self),
                          _CSSFunctionProd(self))
        funcProds = Sequence(
            Prod(name='FUNCTION',
                 match=lambda t, v: t == types.FUNCTION,
                 toSeq=lambda t, tokens: (t[0], normalize(t[1]))),
            Choice(
                Sequence(
                    itemProd,
                    Sequence(PreDef.comma(optional=True),
                             itemProd,
                             minmax=lambda: (0, None)),
                    PreDef.funcEnd(stop=True)), PreDef.funcEnd(stop=True)))
        return funcProds
Esempio n. 27
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods  # rename!
        prods = Sequence(Prod(name='var',
                              match=lambda t, v: t == types.FUNCTION and
                              normalize(v) == 'var('
                              ),
                         PreDef.ident(toStore='ident'),
                         Sequence(PreDef.comma(),
                                  Choice(_ColorProd(self, toStore='fallback'),
                                         _DimensionProd(self, toStore='fallback'),
                                         _URIProd(self, toStore='fallback'),
                                         _ValueProd(self, toStore='fallback'),
                                         _CalcValueProd(self, toStore='fallback'),
                                         _CSSVariableProd(self, toStore='fallback'),
                                         _CSSFunctionProd(self, toStore='fallback')
                                         ),
                                  minmax=lambda: (0, 1)
                                  ),
                         PreDef.funcEnd(stop=True))

        # store: name of variable
        store = {'ident': None, 'fallback': None}
        ok, seq, store, unused = ProdParser().parse(cssText,
                                                    'CSSVariable',
                                                    prods)
        self.wellformed = ok

        if ok:
            self._name = store['ident'].value
            try:
                self._fallback = store['fallback'].value
            except KeyError:
                self._fallback = None

            self._setSeq(seq)
Esempio n. 28
0
    def _productions(self):
        """Return definition used for parsing."""
        types = self._prods  # rename!

        itemProd = Choice(_ColorProd(self),
                          _DimensionProd(self),
                          _URIProd(self),
                          _ValueProd(self),
                          _CalcValueProd(self),
                          _CSSVariableProd(self),
                          _CSSFunctionProd(self)
                          )
        funcProds = Sequence(Prod(name='FUNCTION',
                                  match=lambda t, v: t == types.FUNCTION,
                                  toSeq=lambda t, tokens: (t[0],
                                                           normalize(t[1]))),
                             Choice(Sequence(itemProd,
                                             Sequence(PreDef.comma(optional=True),
                                                      itemProd,
                                                      minmax=lambda: (0, None)),
                                             PreDef.funcEnd(stop=True)),
                                    PreDef.funcEnd(stop=True))
                             )
        return funcProds
Esempio n. 29
0
    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()

        def expression(): return Sequence(PreDef.char(name='expression', char='('),
                                          Prod(name='media_feature',
                                               match=lambda t, v: t == PreDef.types.IDENT
                                               ),
                                          Sequence(PreDef.char(name='colon', char=':'),
                                                   css_parser.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)
                                         )
                                ),
                       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,
                                     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)
                                         )
                                )
                       )

        # 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)
Esempio n. 30
0
    def _setCssText(self, cssText):
        self._checkReadonly()
        types = self._prods  # rename!

        component = Choice(
            PreDef.unary(toSeq=lambda t, tokens: (t[
                0], DimensionValue(pushtoken(t, tokens), parent=self))),
            PreDef.number(toSeq=lambda t, tokens: (t[
                0], DimensionValue(pushtoken(t, tokens), parent=self))),
            PreDef.percentage(toSeq=lambda t, tokens: (t[
                0], DimensionValue(pushtoken(t, tokens), parent=self))))
        noalp = Sequence(
            Prod(name='FUNCTION',
                 match=lambda t, v: t == types.FUNCTION and v.lower() in
                 ('rgb(', 'hsl('),
                 toSeq=lambda t, tokens: (t[0], normalize(t[1]))), component,
            Sequence(PreDef.comma(optional=True),
                     component,
                     minmax=lambda: (2, 2)), PreDef.funcEnd(stop=True))
        witha = Sequence(
            Prod(name='FUNCTION',
                 match=lambda t, v: t == types.FUNCTION and v.lower() in
                 ('rgba(', 'hsla('),
                 toSeq=lambda t, tokens: (t[0], normalize(t[1]))), component,
            Sequence(PreDef.comma(optional=True),
                     component,
                     minmax=lambda: (3, 3)), PreDef.funcEnd(stop=True))
        namedcolor = Prod(name='Named Color',
                          match=lambda t, v: t == 'IDENT' and
                          (normalize(v) in as_list(self.COLORS.keys())),
                          stop=True)

        prods = Choice(PreDef.hexcolor(stop=True), namedcolor, noalp, witha)

        ok, seq, store, unused = ProdParser().parse(cssText, self.type, prods)
        self.wellformed = ok
        if ok:
            t, v = seq[0].type, seq[0].value
            if 'IDENT' == t:
                rgba = self.COLORS[normalize(v)]
            if 'HASH' == t:
                if len(v) == 4:
                    # HASH #rgb
                    rgba = (int(2 * v[1], 16), int(2 * v[2],
                                                   16), int(2 * v[3], 16), 1.0)
                else:
                    # HASH #rrggbb
                    rgba = (int(v[1:3], 16), int(v[3:5], 16), int(v[5:7],
                                                                  16), 1.0)

            elif 'FUNCTION' == t:
                functiontype, raw, check = None, [], ''
                HSL = False

                for item in seq:
                    try:
                        type_ = item.value.type
                    except AttributeError:
                        # type of function, e.g. rgb(
                        if item.type == 'FUNCTION':
                            functiontype = item.value
                            HSL = functiontype in ('hsl(', 'hsla(')
                        continue

                    # save components
                    if type_ == Value.NUMBER:
                        raw.append(item.value.value)
                        check += 'N'
                    elif type_ == Value.PERCENTAGE:
                        if HSL:
                            # save as percentage fraction
                            raw.append(item.value.value / 100.0)
                        else:
                            # save as real value of percentage of 255
                            raw.append(int(255 * item.value.value / 100))
                        check += 'P'

                if HSL:
                    # convert to rgb
                    # h is 360 based (circle)
                    h, s, l_ = raw[0] / 360.0, raw[1], raw[2]
                    # ORDER h l_ s !!!
                    r, g, b = colorsys.hls_to_rgb(h, l_, s)
                    # back to 255 based
                    rgba = [
                        int(round(r * 255)),
                        int(round(g * 255)),
                        int(round(b * 255))
                    ]

                    if len(raw) > 3:
                        rgba.append(raw[3])

                else:
                    # rgb, rgba
                    rgba = raw

                if len(rgba) < 4:
                    rgba.append(1.0)

                # validate
                checks = {
                    'rgb(': ('NNN', 'PPP'),
                    'rgba(': ('NNNN', 'PPPN'),
                    'hsl(': ('NPP', ),
                    'hsla(': ('NPPN', )
                }
                if check not in checks[functiontype]:
                    self._log.error('ColorValue has invalid %s) parameters: '
                                    '%s (N=Number, P=Percentage)' %
                                    (functiontype, check))

            self._colorType = t
            self._red, self._green, self._blue, self._alpha = tuple(rgba)
            self._setSeq(seq)
Esempio n. 31
0
    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()

        def expression():
            return Sequence(
                PreDef.char(name='expression', char='('),
                Prod(name='media_feature',
                     match=lambda t, v: t == PreDef.types.IDENT),
                Sequence(
                    PreDef.char(name='colon', char=':'),
                    css_parser.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))),
            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,
                     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))))

        # 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)
Esempio n. 32
0
    def _setCssText(self, cssText):
        self._checkReadonly()
        types = self._prods  # rename!

        component = Choice(PreDef.unary(toSeq=lambda t, tokens: (t[0],
                                                                 DimensionValue(pushtoken(t, tokens),
                                                                                parent=self)
                                                                 )),
                           PreDef.number(toSeq=lambda t, tokens: (t[0],
                                                                  DimensionValue(pushtoken(t, tokens),
                                                                                 parent=self)
                                                                  )),
                           PreDef.percentage(toSeq=lambda t, tokens: (t[0],
                                                                      DimensionValue(pushtoken(t, tokens),
                                                                                     parent=self)
                                                                      ))
                           )
        noalp = Sequence(Prod(name='FUNCTION',
                              match=lambda t, v: t == types.FUNCTION and
                              v.lower() in ('rgb(', 'hsl('),
                              toSeq=lambda t, tokens: (t[0], normalize(t[1]))),
                         component,
                         Sequence(PreDef.comma(optional=True),
                                  component,
                                  minmax=lambda: (2, 2)
                                  ),
                         PreDef.funcEnd(stop=True)
                         )
        witha = Sequence(Prod(name='FUNCTION',
                              match=lambda t, v: t == types.FUNCTION and
                              v.lower() in ('rgba(', 'hsla('),
                              toSeq=lambda t, tokens: (t[0],
                                                       normalize(t[1]))
                              ),
                         component,
                         Sequence(PreDef.comma(optional=True),
                                  component,
                                  minmax=lambda: (3, 3)
                                  ),
                         PreDef.funcEnd(stop=True)
                         )
        namedcolor = Prod(name='Named Color',
                          match=lambda t, v: t == 'IDENT' and (
                              normalize(v) in as_list(self.COLORS.keys())
                          ),
                          stop=True)

        prods = Choice(PreDef.hexcolor(stop=True),
                       namedcolor,
                       noalp,
                       witha)

        ok, seq, store, unused = ProdParser().parse(cssText,
                                                    self.type,
                                                    prods)
        self.wellformed = ok
        if ok:
            t, v = seq[0].type, seq[0].value
            if 'IDENT' == t:
                rgba = self.COLORS[normalize(v)]
            if 'HASH' == t:
                if len(v) == 4:
                    # HASH #rgb
                    rgba = (int(2*v[1], 16),
                            int(2*v[2], 16),
                            int(2*v[3], 16),
                            1.0)
                else:
                    # HASH #rrggbb
                    rgba = (int(v[1:3], 16),
                            int(v[3:5], 16),
                            int(v[5:7], 16),
                            1.0)

            elif 'FUNCTION' == t:
                functiontype, raw, check = None, [], ''
                HSL = False

                for item in seq:
                    try:
                        type_ = item.value.type
                    except AttributeError:
                        # type of function, e.g. rgb(
                        if item.type == 'FUNCTION':
                            functiontype = item.value
                            HSL = functiontype in ('hsl(', 'hsla(')
                        continue

                    # save components
                    if type_ == Value.NUMBER:
                        raw.append(item.value.value)
                        check += 'N'
                    elif type_ == Value.PERCENTAGE:
                        if HSL:
                            # save as percentage fraction
                            raw.append(item.value.value / 100.0)
                        else:
                            # save as real value of percentage of 255
                            raw.append(int(255 * item.value.value / 100))
                        check += 'P'

                if HSL:
                    # convert to rgb
                    # h is 360 based (circle)
                    h, s, l_ = raw[0] / 360.0, raw[1], raw[2]
                    # ORDER h l_ s !!!
                    r, g, b = colorsys.hls_to_rgb(h, l_, s)
                    # back to 255 based
                    rgba = [int(round(r*255)),
                            int(round(g*255)),
                            int(round(b*255))]

                    if len(raw) > 3:
                        rgba.append(raw[3])

                else:
                    # rgb, rgba
                    rgba = raw

                if len(rgba) < 4:
                    rgba.append(1.0)

                # validate
                checks = {'rgb(': ('NNN', 'PPP'),
                          'rgba(': ('NNNN', 'PPPN'),
                          'hsl(': ('NPP',),
                          'hsla(': ('NPPN',)
                          }
                if check not in checks[functiontype]:
                    self._log.error('ColorValue has invalid %s) parameters: '
                                    '%s (N=Number, P=Percentage)' %
                                    (functiontype, check))

            self._colorType = t
            self._red, self._green, self._blue, self._alpha = tuple(rgba)
            self._setSeq(seq)
Esempio n. 33
0
    def _setCssText(self, cssText):
        """Setting this attribute will result in the parsing of the new value
        and resetting of all the properties in the declaration block
        including the removal or addition of properties.

        :exceptions:
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this declaration is readonly or a property is readonly.
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified CSS string value has a syntax error and
              is unparsable.

        Format::

            variableset
            : vardeclaration [ ';' S* vardeclaration ]*
            ;

            vardeclaration
            : varname ':' S* term
            ;

            varname
            : IDENT S*
            ;

            expr
            : [ VARCALL | term ] [ operator [ VARCALL | term ] ]*
            ;

        """
        self._checkReadonly()

        vardeclaration = Sequence(
            PreDef.ident(),
            PreDef.char(':', ':', toSeq=False, optional=True),
            # PreDef.S(toSeq=False, optional=True),
            Prod(name='term', match=lambda t, v: True,
                 toSeq=lambda t, tokens: ('value',
                                          PropertyValue(itertools.chain([t],
                                                                        tokens),
                                                        parent=self)
                                          )
                 )
        )
        prods = Sequence(vardeclaration,
                         Sequence(PreDef.S(optional=True),
                                  PreDef.char(';', ';', toSeq=False, optional=True),
                                  PreDef.S(optional=True),
                                  vardeclaration,
                                  minmax=lambda: (0, None)),
                         PreDef.S(optional=True),
                         PreDef.char(';', ';', toSeq=False, optional=True)
                         )
        # parse
        wellformed, seq, store, notused = \
            ProdParser().parse(cssText,
                               'CSSVariableDeclaration',
                               prods,
                               emptyOk=True)
        if wellformed:
            newseq = self._tempSeq()
            newvars = {}

            # seq contains only name: value pairs plus comments etc
            nameitem = None
            for item in seq:
                if 'IDENT' == item.type:
                    nameitem = item
                elif 'value' == item.type:
                    nname = normalize(nameitem.value)
                    if nname in newvars:
                        # replace var with same name
                        for i, it in enumerate(newseq):
                            if normalize(it.value[0]) == nname:
                                newseq.replace(i,
                                               (nameitem.value, item.value),
                                               'var',
                                               nameitem.line, nameitem.col)
                    else:
                        # saved non normalized name for reserialization
                        newseq.append((nameitem.value, item.value),
                                      'var',
                                      nameitem.line, nameitem.col)

#                    newseq.append((nameitem.value, item.value),
#                                  'var',
#                                  nameitem.line, nameitem.col)

                    newvars[nname] = item.value

                else:
                    newseq.appendItem(item)

            self._setSeq(newseq)
            self._vars = newvars
            self.wellformed = True
Esempio n. 34
0
    def _setCssText(self, cssText):
        """Setting this attribute will result in the parsing of the new value
        and resetting of all the properties in the declaration block
        including the removal or addition of properties.

        :exceptions:
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this declaration is readonly or a property is readonly.
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified CSS string value has a syntax error and
              is unparsable.

        Format::

            variableset
            : vardeclaration [ ';' S* vardeclaration ]*
            ;

            vardeclaration
            : varname ':' S* term
            ;

            varname
            : IDENT S*
            ;

            expr
            : [ VARCALL | term ] [ operator [ VARCALL | term ] ]*
            ;

        """
        self._checkReadonly()

        vardeclaration = Sequence(
            PreDef.ident(),
            PreDef.char(':', ':', toSeq=False, optional=True),
            # PreDef.S(toSeq=False, optional=True),
            Prod(name='term',
                 match=lambda t, v: True,
                 toSeq=lambda t, tokens:
                 ('value',
                  PropertyValue(itertools.chain([t], tokens), parent=self))))
        prods = Sequence(
            vardeclaration,
            Sequence(PreDef.S(optional=True),
                     PreDef.char(';', ';', toSeq=False, optional=True),
                     PreDef.S(optional=True),
                     vardeclaration,
                     minmax=lambda: (0, None)), PreDef.S(optional=True),
            PreDef.char(';', ';', toSeq=False, optional=True))
        # parse
        wellformed, seq, store, notused = \
            ProdParser().parse(cssText,
                               'CSSVariableDeclaration',
                               prods,
                               emptyOk=True)
        if wellformed:
            newseq = self._tempSeq()
            newvars = {}

            # seq contains only name: value pairs plus comments etc
            nameitem = None
            for item in seq:
                if 'IDENT' == item.type:
                    nameitem = item
                elif 'value' == item.type:
                    nname = normalize(nameitem.value)
                    if nname in newvars:
                        # replace var with same name
                        for i, it in enumerate(newseq):
                            if normalize(it.value[0]) == nname:
                                newseq.replace(i, (nameitem.value, item.value),
                                               'var', nameitem.line,
                                               nameitem.col)
                    else:
                        # saved non normalized name for reserialization
                        newseq.append((nameitem.value, item.value), 'var',
                                      nameitem.line, nameitem.col)

#                    newseq.append((nameitem.value, item.value),
#                                  'var',
#                                  nameitem.line, nameitem.col)

                    newvars[nname] = item.value

                else:
                    newseq.appendItem(item)

            self._setSeq(newseq)
            self._vars = newvars
            self.wellformed = True