Exemple #1
0
def _ColorProd(parent, nextSor=False):
    return Prod(
        name='ColorValue',
        match=lambda t, v: t == 'HASH' or
        (t == 'FUNCTION' and normalize(v) in
         (u'rgb(', u'rgba(', u'hsl(', u'hsla(')) or
        (t == 'IDENT' and normalize(v) in ColorValue.COLORS.keys()),
        nextSor=nextSor,
        toSeq=lambda t, tokens:
        ('ColorValue', ColorValue(pushtoken(t, tokens), parent=parent)))
Exemple #2
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),
                               u'variableName',
                               Sequence(PreDef.ident()))
        if not wellformed:
            self._log.error(u'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(u'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
    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),
                               u'variableName',
                               Sequence(PreDef.ident()))
        if not wellformed:
            self._log.error(u'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(u'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
Exemple #4
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 list(ColorValue.COLORS.keys())),
        nextSor=nextSor,
        toStore=toStore,
        toSeq=lambda t, tokens:
        ('ColorValue', ColorValue(pushtoken(t, tokens), parent=parent)))
Exemple #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:`~cssutils.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
Exemple #6
0
 def test_normalize(self):
     "helper._normalize()"
     tests = {
         'abcdefg ABCDEFG äöü߀ AÖÜ': r'abcdefg abcdefg äöü߀ aöü',
         r'\ga\Ga\\\ ': r'gaga\ ',
         r'0123456789': r'0123456789',
         r'"\x"': r'"x"',
         # unicode escape seqs should have been done by
         # the tokenizer...
     }
     for test, exp in list(tests.items()):
         self.assertEqual(normalize(test), exp)
         # static too
         self.assertEqual(normalize(test), exp)
Exemple #7
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)
Exemple #8
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 u'var' == type_:
                    name, cssvalue = val
                    if self.prefs.normalizedVarNames:
                        name = normalize(name)
                    out.append(name)
                    out.append(u':')
                    out.append(cssvalue.cssText)
                    if i < lastitem or not self.prefs.omitLastSemicolon:
                        out.append(u';')

                elif isinstance(val, cssutils.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 u''
Exemple #9
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)
 def __contains__(self, variableName):
     """Check if a variable is in variable declaration block.
     
     :param variableName:
         a string
     """
     return normalize(variableName) in self.keys()
    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 u'var' == type_:
                    name, cssvalue = val
                    if self.prefs.normalizedVarNames:
                        name = normalize(name)
                    out.append(name)
                    out.append(u':')
                    out.append(cssvalue.cssText)
                    if i < lastitem or not self.prefs.omitLastSemicolon:
                        out.append(u';')

                elif isinstance(val, cssutils.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 u''
Exemple #12
0
 def __contains__(self, variableName):
     """Check if a variable is in variable declaration block.
     
     :param variableName:
         a string
     """
     return normalize(variableName) in list(self.keys())
Exemple #13
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,
                                                    u'DimensionValue',
                                                    prods)
        self.wellformed = ok
        if ok:
            item = seq[0]

            sign, v, d = self.__reUnNumDim.findall(
                                normalize(item.value))[0]
            if u'.' 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)
Exemple #14
0
def _MSValueProd(parent, nextSor=False):
    return Prod(name=MSValue._functionName,
                match=lambda t, v: (#t == self._prods.FUNCTION and (
                    normalize(v) in (u'expression(',
                                                     u'alpha(',
                                                     u'blur(',
                                                     u'chroma(',
                                                     u'dropshadow(',
                                                     u'fliph(',
                                                     u'flipv(',
                                                     u'glow(',
                                                     u'gray(',
                                                     u'invert(',
                                                     u'mask(',
                                                     u'shadow(',                                                               
                                                     u'wave(',
                                                     u'xray(') or
                    v.startswith(u'progid:DXImageTransform.Microsoft.')                               
                    ),
                nextSor=nextSor,
                toSeq=lambda t, tokens: (MSValue._functionName, 
                                         MSValue(pushtoken(t, 
                                                                           tokens
                                                                           ),
                                                 parent=parent
                                                 )
                                         )
                )
Exemple #15
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),
        ),
    )
Exemple #16
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
    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:`~cssutils.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 u'all' in mts:
                self._log.info(u'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 u'all' == newmt:
                    self._clearSeq()

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

            self._seq._readonly = True

            return True

        else:
            return False
Exemple #18
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),
                ),
            ),
        )

        _operant = lambda: Choice(  # noqa:E731
            _DimensionProd(self), _CalcValueProd(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)
Exemple #19
0
def _ColorProd(parent, nextSor=False):
    return Prod(name='ColorValue',
                match=lambda t, v: t == 'HASH' or 
                                   (t == 'FUNCTION' and
                                    normalize(v) in (u'rgb(', 
                                                     u'rgba(',
                                                     u'hsl(', 
                                                     u'hsla(')) or
                                   (t == 'IDENT' and 
                                    normalize(v) in ColorValue.COLORS.keys()
                                    ),
                nextSor = nextSor,
                toSeq=lambda t, tokens: ('ColorValue', ColorValue(
                                            pushtoken(t, 
                                                                      tokens),
                                         parent=parent)
                                         )
                )
Exemple #20
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)
Exemple #21
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods # rename!

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

        _operant = lambda: Choice(_DimensionProd(self),
                                   _CSSVariableProd(self))

        prods = Sequence(Prod(name='CALC',
                                  match=lambda t, v: t == types.FUNCTION and
                                        normalize(v) == u'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,
                                                    u'CSSCalc',
                                                    prods,
                                                    checkS=True)
        self.wellformed = ok
        if ok:
            self._setSeq(seq)
Exemple #22
0
def _CalcValueProd(parent, nextSor=False, toStore=None):
    return Prod(name=CSSCalc._functionName,
                    match=lambda t, v: t == PreDef.types.FUNCTION and
                        normalize(v) == u'calc(',
                    toStore=toStore,
                    toSeq=lambda t, tokens: (CSSCalc._functionName,
                                                    CSSCalc(
                                pushtoken(t, tokens),
                                parent=parent)
                                                    ),
                    nextSor=nextSor)
    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(u'"%s" not in this MediaList' % oldMedium,
                            error=xml.dom.NotFoundErr)
Exemple #24
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)
Exemple #25
0
    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')
 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, e:
         return u''
Exemple #27
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 as e:
         return ''
    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(
                u'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, basestring):
                    if normalize(x.value) in (u'only', u'not'):
                        continue
                    else:
                        # TODO: simplify!
                        self._seq[i] = (mediaType, 'IDENT', None, None)
                        break
            else:
                self._seq.insert(0, mediaType, 'IDENT')
Exemple #29
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) ==
                 u'var('), PreDef.ident(toStore='ident'),
            PreDef.funcEnd(stop=True))

        # store: name of variable
        store = {'ident': None}
        ok, seq, store, unused = ProdParser().parse(cssText, u'CSSVariable',
                                                    prods)
        if ok:
            self._name = store['ident'].value
            self._setSeq(seq)
            self.wellformed = ok
    def removeVariable(self, variableName):
        """Used to remove 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 for this
            variable declaration block. Returns the empty string if the
            variable has not been set.

        :exceptions:
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this declaration is readonly is readonly.
        """
        try:
            r = self._vars[normalize(variableName)]
        except KeyError, e:
            return u''
Exemple #31
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) == u'var(' 
                             ),
                             PreDef.ident(toStore='ident'),
                             PreDef.funcEnd(stop=True))
        
        # store: name of variable
        store = {'ident': None}
        ok, seq, store, unused = ProdParser().parse(cssText, 
                                                    u'CSSVariable',
                                                    prods)
        if ok:
            self._name = store['ident'].value
            self._setSeq(seq)
            self.wellformed = ok
Exemple #32
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, 
                                                    u'DimensionValue', 
                                                    prods)
        if ok:
            sign = val = u''
            dim = type_ = None
            
            # find 
            for item in seq:
                if item.value in u'+-':
                    sign = item.value
                else:
                    type_ = item.type
                    
                    # number + optional dim
                    v, d = self.__reNumDim.findall(
                                normalize(item.value))[0]
                    if u'.' in v:
                        val = float(sign + v)
                    else:
                        val = int(sign + v)
                    if d:
                        dim = d

            self._sign = sign                                                    
            self._value = val
            self._dimension = dim
            self._type = type_

            self._setSeq(seq)
            self.wellformed = ok
Exemple #33
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) == u'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,
                                                    u'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)
Exemple #34
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, u'DimensionValue',
                                                    prods)
        if ok:
            sign = val = u''
            dim = type_ = None

            # find
            for item in seq:
                if item.value in u'+-':
                    sign = item.value
                else:
                    type_ = item.type

                    # number + optional dim
                    v, d = self.__reNumDim.findall(normalize(item.value))[0]
                    if u'.' in v:
                        val = float(sign + v)
                    else:
                        val = int(sign + v)
                    if d:
                        dim = d

            self._sign = sign
            self._value = val
            self._dimension = dim
            self._type = type_

            self._setSeq(seq)
            self.wellformed = ok
Exemple #35
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(),
                                                   itemProd,
                                                   minmax=lambda: (0, None)),
                                          PreDef.funcEnd(stop=True)),
                                 PreDef.funcEnd(stop=True))
      )
     return funcProds
    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(PreDef.char(name='expression', char=u'('),
                                      Prod(name=u'media_feature',
                                           match=lambda t, v: t == PreDef.types.IDENT
                                      ),
                                      Sequence(PreDef.char(name='colon', char=u':'),
                                               cssutils.css.value.MediaQueryValueProd(self),
                                               minmax=lambda: (0, 1) # optional
                                               ),
                                      PreDef.char(name='expression END', char=u')',
                                                  stopIfNoMoreMatch=self._partof
                                                  )
                                      )

        prods = Choice(Sequence(Prod(name=u'ONLY|NOT', # media_query
                                     match=lambda t, v: t == PreDef.types.IDENT and 
                                                        normalize(v) in (u'only', u'not'),
                                     optional=True,
                                     toStore='not simple'
                                     ), 
                                Prod(name=u'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=u'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=u'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, 
                                                    u'MediaQuery',
                                                    prods)
        self._wellformed = ok
        if ok:
            try:
                media_type = store['media_type']
            except KeyError, e:
                pass
            else:
                if 'not simple' not in store:
                    self.mediaType = media_type.value

            # TODO: filter doubles!
            self._setSeq(seq)
Exemple #37
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
        :exceptions:
            - :exc:`~xml.dom.NoModificationAllowedErr`:
              Raised if this declaration is readonly is readonly.
        """
        try:
            r = self._vars[normalize(variableName)]
        except KeyError, e:
            return u''
        else: 
            self.seq._readonly = False
            if variableName in self._vars:
                for i, x in enumerate(self.seq):
                    if x.value[0] == variableName:
                        del self.seq[i]
            self.seq._readonly = True
            del self._vars[normalize(variableName)]

        return r.cssText

    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 CSSValue object.

        :exceptions:
            - :exc:`~xml.dom.SyntaxErr`:
              Raised if the specified value has a syntax error and is
              unparsable.
 def __setitem__(self, variableName, value):
     self.setVariable(normalize(variableName), value)
 def __getitem__(self, variableName):
     """Retrieve the value of variable ``variableName`` from this 
     declaration.
     """
     return self.getVariableValue(normalize(variableName))
Exemple #41
0
    def _setCssText(self, cssText):  # noqa: C901
        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 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 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 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)
 def __delitem__(self, variableName):
     return self.removeVariable(normalize(variableName))
Exemple #43
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 in
                 (u'rgb(', u'hsl('),
                 toSeq=lambda t, tokens: (t[0], normalize(t[1]))), component,
            Sequence(PreDef.comma(), component, minmax=lambda: (2, 2)),
            PreDef.funcEnd(stop=True))
        witha = Sequence(
            Prod(name='FUNCTION',
                 match=lambda t, v: t == types.FUNCTION and v in
                 (u'rgba(', u'hsla('),
                 toSeq=lambda t, tokens: (t[0], normalize(t[1]))), component,
            Sequence(PreDef.comma(), component, minmax=lambda: (3, 3)),
            PreDef.funcEnd(stop=True))
        namedcolor = Prod(name='Named Color',
                          match=lambda t, v: t == 'IDENT' and
                          (normalize(v) in self.COLORS.keys()),
                          stop=True)

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

        ok, seq, store, unused = ProdParser().parse(cssText, self.type, prods)
        if ok:
            t, v = seq[0].type, seq[0].value
            if u'IDENT' == t:
                rgba = self.COLORS[normalize(v)]
            if u'HASH' == t:
                if len(v) == 4:
                    # HASH #rgb
                    rgba = (int(2 * v[1], 16), int(2 * v[1],
                                                   16), int(2 * v[1], 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 u'FUNCTION' == t:
                functiontype, rgba, check = None, [], u''
                for item in seq:
                    try:
                        type_ = item.value.type
                    except AttributeError, e:
                        # type of function, e.g. rgb(
                        if item.type == 'FUNCTION':
                            functiontype = item.value
                        continue

                    # save components
                    if type_ == Value.NUMBER:
                        rgba.append(item.value.value)
                        check += u'N'
                    elif type_ == Value.PERCENTAGE:
                        rgba.append(int(255 * item.value.value / 100))
                        check += u'P'

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

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

            self._colorType = t
            self._red, self._green, self._blue, self._alpha = tuple(rgba)
            self._setSeq(seq)
            self.wellformed = ok
Exemple #44
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 in (u'rgb(', u'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 in (u'rgba(', u'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 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 u'IDENT' == t:
                rgba = self.COLORS[normalize(v)]
            if u'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 u'FUNCTION' == t:
                functiontype, raw, check = None, [], u''
                HSL = False

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

                    # save components
                    if type_ == Value.NUMBER:
                        raw.append(item.value.value)
                        check += u'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 += u'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 = {u'rgb(': ('NNN', 'PPP'),
                         u'rgba(': ('NNNN', 'PPPN'),
                         u'hsl(': ('NPP',),
                         u'hsla(': ('NPPN',)
                         }
                if check not in checks[functiontype]:
                    self._log.error(u'ColorValue has invalid %s) parameters: '
                                    u'%s (N=Number, P=Percentage)' %
                                    (functiontype, check))

            self._colorType = t
            self._red, self._green, self._blue, self._alpha = tuple(rgba)
            self._setSeq(seq)
    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(u':', u':', toSeq=False),
            #PreDef.S(toSeq=False, optional=True),
            Prod(name=u'term', match=lambda t, v: True,
                 toSeq=lambda t, tokens: (u'value', 
                                          PropertyValue(itertools.chain([t], 
                                                                        tokens), 
                                          parent=self)
                 )
            )            
        )
        prods = Sequence(vardeclaration,                         
                         Sequence(PreDef.S(optional=True),
                                  PreDef.char(u';', u';', toSeq=False),
                                  PreDef.S(optional=True),
                                  vardeclaration,
                                  minmax=lambda: (0, None)),
                         PreDef.S(optional=True),
                         PreDef.char(u';', u';', toSeq=False, optional=True) 
                         )
        # parse
        wellformed, seq, store, notused = \
            ProdParser().parse(cssText, 
                               u'CSSVariableDeclaration',
                               prods)
        if wellformed:
            newseq = self._tempSeq()
            newvars = {}

            # seq contains only name: value pairs plus comments etc
            nameitem = None
            for item in seq:
                if u'IDENT' == item.type:
                    nameitem = item
                elif u'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
Exemple #46
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()

        expression = lambda: Sequence(
            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 as e:
                pass
            else:
                if 'not simple' not in store:
                    self.mediaType = media_type.value

            # TODO: filter doubles!
            self._setSeq(seq)
Exemple #47
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 in (u'rgb(', u'hsl('),
                              toSeq=lambda t, tokens: (t[0], normalize(t[1]))),
                          component,
                          Sequence(PreDef.comma(), 
                                   component,
                                   minmax=lambda: (2, 2)
                                   ),
                          PreDef.funcEnd(stop=True)
                          )
        witha = Sequence(Prod(name='FUNCTION',
                              match=lambda t, v: t == types.FUNCTION and
                                                 v in (u'rgba(', u'hsla('),
                              toSeq=lambda t, tokens: (t[0], 
                                 normalize(t[1]))
                              ),
                          component,
                          Sequence(PreDef.comma(), 
                                   component,
                                   minmax=lambda: (3, 3)
                                   ),
                          PreDef.funcEnd(stop=True)
                          )
        namedcolor = Prod(name='Named Color',
                     match=lambda t, v: t == 'IDENT' and (
                                        normalize(v) in self.COLORS.keys()
                                        ),
                     stop=True)
        
        prods = Choice(PreDef.hexcolor(stop=True), 
                       namedcolor, 
                       noalp, 
                       witha)
        
        ok, seq, store, unused = ProdParser().parse(cssText, 
                                                    self.type,
                                                    prods)
        if ok:
            t, v = seq[0].type, seq[0].value
            if u'IDENT' == t:
                rgba = self.COLORS[normalize(v)]
            if u'HASH' == t:
                if len(v) == 4:
                    # HASH #rgb
                    rgba = (int(2*v[1], 16),
                            int(2*v[1], 16),
                            int(2*v[1], 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 u'FUNCTION' == t:
                functiontype, rgba, check = None, [], u''
                for item in seq:
                    try:
                        type_ = item.value.type
                    except AttributeError, e:
                        # type of function, e.g. rgb(
                        if item.type == 'FUNCTION':
                            functiontype = item.value
                        continue

                    # save components                    
                    if type_ == Value.NUMBER:
                        rgba.append(item.value.value)
                        check += u'N'
                    elif type_ == Value.PERCENTAGE:
                        rgba.append(int(255 * item.value.value / 100))
                        check += u'P'
                        
                # validate
                checks = {u'rgb(': ('NNN', 'PPP'),
                         u'rgba(': ('NNNN', 'PPPN'),
                         u'hsl(': ('NPP',),
                         u'hsla(': ('NPPN',)
                         }
                if check not in checks[functiontype]:
                    self._log.error(u'ColorValue has invalid %s) parameters: '
                                    u'%s (N=Number, P=Percentage)' % 
                                    (functiontype, check))
                    
                if len(rgba) < 4:
                    rgba.append(1.0)
            
            self._colorType = t
            self._red, self._green, self._blue, self._alpha = tuple(rgba)
            self._setSeq(seq)
            self.wellformed = ok