コード例 #1
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
コード例 #2
0
ファイル: value.py プロジェクト: wcq062821/Sigil
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)))
コード例 #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
コード例 #4
0
ファイル: medialist.py プロジェクト: wcq062821/Sigil
    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
コード例 #5
0
ファイル: medialist.py プロジェクト: Sigil-Ebook/Sigil
    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
コード例 #6
0
ファイル: value.py プロジェクト: wcq062821/Sigil
    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)
コード例 #7
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
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
                                                 )
                                         )
                )
コード例 #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
                                                 )
                                         )
                )
コード例 #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())
コード例 #10
0
ファイル: value.py プロジェクト: wcq062821/Sigil
    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)
コード例 #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())
コード例 #12
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
    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)
コード例 #13
0
ファイル: serialize.py プロジェクト: Sigil-Ebook/Sigil
    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 ''
コード例 #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 ''
コード例 #15
0
ファイル: value.py プロジェクト: wcq062821/Sigil
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)
コード例 #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)
コード例 #17
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
    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)
コード例 #18
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
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)
コード例 #19
0
ファイル: medialist.py プロジェクト: Sigil-Ebook/Sigil
    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)
コード例 #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)
コード例 #21
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
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)
                )
                )
コード例 #22
0
ファイル: mediaquery.py プロジェクト: Sigil-Ebook/Sigil
    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')
コード例 #23
0
ファイル: mediaquery.py プロジェクト: wcq062821/Sigil
    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')
コード例 #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 ''
コード例 #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 ''
コード例 #26
0
ファイル: value.py プロジェクト: wcq062821/Sigil
    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
コード例 #27
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
    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)
コード例 #28
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
    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
コード例 #29
0
ファイル: mediaquery.py プロジェクト: Sigil-Ebook/Sigil
    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)
コード例 #30
0
ファイル: value.py プロジェクト: wcq062821/Sigil
    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)
コード例 #31
0
ファイル: mediaquery.py プロジェクト: wcq062821/Sigil
    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)
コード例 #32
0
ファイル: value.py プロジェクト: Sigil-Ebook/Sigil
    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)
コード例 #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
コード例 #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