Ejemplo n.º 1
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
Ejemplo n.º 2
0
    def _setCssText(self, cssText):
        self._checkReadonly()
        types = self._prods  # rename!
        valueProd = Prod(
            name='value',
            match=lambda t, v: t in (types.NUMBER, types.PERCENTAGE),
            toSeq=lambda t, v: (CSSPrimitiveValue, CSSPrimitiveValue(v)),
            toStore='parts',
        )
        # COLOR PRODUCTION
        funccolor = Sequence(
            Prod(
                name='FUNC',
                match=lambda t, v: t == types.FUNCTION and cssutils.helper.
                normalize(v) in ('rgb(', 'rgba(', 'hsl(', 'hsla('),
                toSeq=lambda t, v: (t, v),  # cssutils.helper.normalize(v)),
                toStore='colorType',
            ),
            PreDef.unary(),
            valueProd,
            # 2 or 3 more values starting with Comma
            Sequence(PreDef.comma(),
                     PreDef.unary(),
                     valueProd,
                     minmax=lambda: (2, 3)),
            PreDef.funcEnd(),
        )
        colorprods = Choice(
            funccolor,
            PreDef.hexcolor('colorType'),
            Prod(
                name='named color',
                match=lambda t, v: t == types.IDENT,
                toStore='colorType',
            ),
        )
        # store: colorType, parts
        wellformed, seq, store, unusedtokens = ProdParser().parse(
            cssText, 'RGBColor', colorprods, keepS=True, store={'parts': []})

        if wellformed:
            self.wellformed = True
            if store['colorType'].type == self._prods.HASH:
                self._colorType = 'HEX'
            elif store['colorType'].type == self._prods.IDENT:
                self._colorType = 'Named Color'
            else:
                self._colorType = store['colorType'].value[:-1]
                # self._colorType = \
                # cssutils.helper.normalize(store['colorType'].value)[:-1]

            self._setSeq(seq)
Ejemplo n.º 3
0
    def _productiondefinition(self):
        """Return definition used for parsing."""
        types = self._prods  # rename!

        value = Sequence(
            PreDef.unary(),
            Prod(
                name='PrimitiveValue',
                match=lambda t, v: t in (
                    types.DIMENSION,
                    types.HASH,
                    types.IDENT,
                    types.NUMBER,
                    types.PERCENTAGE,
                    types.STRING,
                ),
                toSeq=lambda t, tokens: (t[0], CSSPrimitiveValue(t[1])),
            ),
        )
        valueOrFunc = Choice(
            value,
            # FUNC is actually not in spec but used in e.g. Prince
            PreDef.function(toSeq=lambda t, tokens: (
                'FUNCTION',
                CSSFunction(cssutils.helper.pushtoken(t, tokens)),
            )),
        )
        funcProds = Sequence(
            Prod(
                name='FUNC',
                match=lambda t, v: t == types.FUNCTION,
                toSeq=lambda t, tokens:
                (t[0], cssutils.helper.normalize(t[1])),
            ),
            Choice(
                Sequence(
                    valueOrFunc,
                    # more values starting with Comma
                    # should use store where colorType is saved to
                    # define min and may, closure?
                    Sequence(PreDef.comma(),
                             valueOrFunc,
                             minmax=lambda: (0, None)),
                    PreDef.funcEnd(stop=True),
                ),
                PreDef.funcEnd(stop=True),
            ),
        )
        return funcProds
Ejemplo n.º 4
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)
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def _setMediaText(self, mediaText):  # noqa: C901
        """
        :param mediaText:
            simple value or comma-separated list of media

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

        mediaquery = lambda: Prod(  # noqa
            name='MediaQueryStart',
            match=lambda t, v: t == 'IDENT' or v == '(',
            toSeq=lambda t, tokens: (
                'MediaQuery',
                MediaQuery(pushtoken(t, tokens), _partof=True),
            ),
        )
        prods = Sequence(
            Sequence(PreDef.comment(parent=self), minmax=lambda: (0, None)),
            mediaquery(),
            Sequence(PreDef.comma(toSeq=False),
                     mediaquery(),
                     minmax=lambda: (0, None)),
        )
        # parse
        ok, seq, store, unused = ProdParser().parse(mediaText,
                                                    'MediaList',
                                                    prods,
                                                    debug="ml")

        # each mq must be valid
        atleastone = False

        for item in seq:
            v = item.value
            if isinstance(v, MediaQuery):
                if not v.wellformed:
                    ok = False
                    break
                else:
                    atleastone = True

        # must be at least one value!
        if not atleastone:
            ok = False
            self._wellformed = ok
            self._log.error('MediaQuery: No content.', error=xml.dom.SyntaxErr)

        self._wellformed = ok

        if ok:
            mediaTypes = []
            finalseq = cssutils.util.Seq(readonly=False)
            commentseqonly = cssutils.util.Seq(readonly=False)
            for item in seq:
                # filter for doubles?
                if item.type == 'MediaQuery':
                    mediaType = item.value.mediaType
                    if mediaType:
                        if mediaType == 'all':
                            # remove anthing else and keep all+comments(!) only
                            finalseq = commentseqonly
                            finalseq.append(item)
                            break
                        elif mediaType in mediaTypes:
                            continue
                        else:
                            mediaTypes.append(mediaType)
                elif isinstance(item.value,
                                cssutils.css.csscomment.CSSComment):
                    commentseqonly.append(item)

                finalseq.append(item)

            self._setSeq(finalseq)