Hide navigation sidebar
Hide table of contents sidebar
Back to top
Toggle table of contents sidebar

# Source code for nodriver.cdp.css

    # DO NOT EDIT THIS FILE!
    #
    # This file is generated from the CDP specification. If you need to make
    # changes, edit the generator and regenerate all of the modules.
    #
    # CDP domain: CSS (experimental)

    from __future__ import annotations
    import enum
    import typing
    from dataclasses import dataclass
    from .util import event_class, T_JSON_DICT

    from . import dom
    from . import page

    class StyleSheetId(str):
        def to_json(self) -> str:
            return self

        @classmethod
        def from_json(cls, json: str) -> StyleSheetId:
            return cls(json)

        def __repr__(self):
            return 'StyleSheetId({})'.format(super().__repr__())

    class StyleSheetOrigin(enum.Enum):
        '''
        Stylesheet type: "injected" for stylesheets injected via extension, "user-agent" for user-agent
        stylesheets, "inspector" for stylesheets created by the inspector (i.e. those holding the "via
        inspector" rules), "regular" for regular stylesheets.
        '''
        INJECTED = "injected"
        USER_AGENT = "user-agent"
        INSPECTOR = "inspector"
        REGULAR = "regular"

        def to_json(self) -> str:
            return self.value

        @classmethod
        def from_json(cls, json: str) -> StyleSheetOrigin:
            return cls(json)

    @dataclass
    class PseudoElementMatches:
        '''
        CSS rule collection for a single pseudo style.
        '''
        #: Pseudo element type.
        pseudo_type: dom.PseudoType

        #: Matches of CSS rules applicable to the pseudo style.
        matches: typing.List[RuleMatch]

        #: Pseudo element custom ident.
        pseudo_identifier: typing.Optional[str] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['pseudoType'] = self.pseudo_type.to_json()
            json['matches'] = [i.to_json() for i in self.matches]
            if self.pseudo_identifier is not None:
                json['pseudoIdentifier'] = self.pseudo_identifier
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> PseudoElementMatches:
            return cls(
                pseudo_type=dom.PseudoType.from_json(json['pseudoType']),
                matches=[RuleMatch.from_json(i) for i in json['matches']],
                pseudo_identifier=str(json['pseudoIdentifier']) if json.get('pseudoIdentifier', None) is not None else None,
            )

    @dataclass
    class CSSAnimationStyle:
        '''
        CSS style coming from animations with the name of the animation.
        '''
        #: The style coming from the animation.
        style: CSSStyle

        #: The name of the animation.
        name: typing.Optional[str] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['style'] = self.style.to_json()
            if self.name is not None:
                json['name'] = self.name
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSAnimationStyle:
            return cls(
                style=CSSStyle.from_json(json['style']),
                name=str(json['name']) if json.get('name', None) is not None else None,
            )

    @dataclass
    class InheritedStyleEntry:
        '''
        Inherited CSS rule collection from ancestor node.
        '''
        #: Matches of CSS rules matching the ancestor node in the style inheritance chain.
        matched_css_rules: typing.List[RuleMatch]

        #: The ancestor node's inline style, if any, in the style inheritance chain.
        inline_style: typing.Optional[CSSStyle] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['matchedCSSRules'] = [i.to_json() for i in self.matched_css_rules]
            if self.inline_style is not None:
                json['inlineStyle'] = self.inline_style.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> InheritedStyleEntry:
            return cls(
                matched_css_rules=[RuleMatch.from_json(i) for i in json['matchedCSSRules']],
                inline_style=CSSStyle.from_json(json['inlineStyle']) if json.get('inlineStyle', None) is not None else None,
            )

    @dataclass
    class InheritedAnimatedStyleEntry:
        '''
        Inherited CSS style collection for animated styles from ancestor node.
        '''
        #: Styles coming from the animations of the ancestor, if any, in the style inheritance chain.
        animation_styles: typing.Optional[typing.List[CSSAnimationStyle]] = None

        #: The style coming from the transitions of the ancestor, if any, in the style inheritance chain.
        transitions_style: typing.Optional[CSSStyle] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            if self.animation_styles is not None:
                json['animationStyles'] = [i.to_json() for i in self.animation_styles]
            if self.transitions_style is not None:
                json['transitionsStyle'] = self.transitions_style.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> InheritedAnimatedStyleEntry:
            return cls(
                animation_styles=[CSSAnimationStyle.from_json(i) for i in json['animationStyles']] if json.get('animationStyles', None) is not None else None,
                transitions_style=CSSStyle.from_json(json['transitionsStyle']) if json.get('transitionsStyle', None) is not None else None,
            )

    @dataclass
    class InheritedPseudoElementMatches:
        '''
        Inherited pseudo element matches from pseudos of an ancestor node.
        '''
        #: Matches of pseudo styles from the pseudos of an ancestor node.
        pseudo_elements: typing.List[PseudoElementMatches]

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['pseudoElements'] = [i.to_json() for i in self.pseudo_elements]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> InheritedPseudoElementMatches:
            return cls(
                pseudo_elements=[PseudoElementMatches.from_json(i) for i in json['pseudoElements']],
            )

    @dataclass
    class RuleMatch:
        '''
        Match data for a CSS rule.
        '''
        #: CSS rule in the match.
        rule: CSSRule

        #: Matching selector indices in the rule's selectorList selectors (0-based).
        matching_selectors: typing.List[int]

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['rule'] = self.rule.to_json()
            json['matchingSelectors'] = [i for i in self.matching_selectors]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> RuleMatch:
            return cls(
                rule=CSSRule.from_json(json['rule']),
                matching_selectors=[int(i) for i in json['matchingSelectors']],
            )

    @dataclass
    class Value:
        '''
        Data for a simple selector (these are delimited by commas in a selector list).
        '''
        #: Value text.
        text: str

        #: Value range in the underlying resource (if available).
        range_: typing.Optional[SourceRange] = None

        #: Specificity of the selector.
        specificity: typing.Optional[Specificity] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['text'] = self.text
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.specificity is not None:
                json['specificity'] = self.specificity.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> Value:
            return cls(
                text=str(json['text']),
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                specificity=Specificity.from_json(json['specificity']) if json.get('specificity', None) is not None else None,
            )

    @dataclass
    class Specificity:
        '''
        Specificity:
        https://drafts.csswg.org/selectors/#specificity-rules
        '''
        #: The a component, which represents the number of ID selectors.
        a: int

        #: The b component, which represents the number of class selectors, attributes selectors, and
        #: pseudo-classes.
        b: int

        #: The c component, which represents the number of type selectors and pseudo-elements.
        c: int

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['a'] = self.a
            json['b'] = self.b
            json['c'] = self.c
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> Specificity:
            return cls(
                a=int(json['a']),
                b=int(json['b']),
                c=int(json['c']),
            )

    @dataclass
    class SelectorList:
        '''
        Selector list data.
        '''
        #: Selectors in the list.
        selectors: typing.List[Value]

        #: Rule selector text.
        text: str

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['selectors'] = [i.to_json() for i in self.selectors]
            json['text'] = self.text
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> SelectorList:
            return cls(
                selectors=[Value.from_json(i) for i in json['selectors']],
                text=str(json['text']),
            )

    @dataclass
    class CSSStyleSheetHeader:
        '''
        CSS stylesheet metainformation.
        '''
        #: The stylesheet identifier.
        style_sheet_id: StyleSheetId

        #: Owner frame identifier.
        frame_id: page.FrameId

        #: Stylesheet resource URL. Empty if this is a constructed stylesheet created using
        #: new CSSStyleSheet() (but non-empty if this is a constructed stylesheet imported
        #: as a CSS module script).
        source_url: str

        #: Stylesheet origin.
        origin: StyleSheetOrigin

        #: Stylesheet title.
        title: str

        #: Denotes whether the stylesheet is disabled.
        disabled: bool

        #: Whether this stylesheet is created for STYLE tag by parser. This flag is not set for
        #: document.written STYLE tags.
        is_inline: bool

        #: Whether this stylesheet is mutable. Inline stylesheets become mutable
        #: after they have been modified via CSSOM API.
        #: ``<link>`` element's stylesheets become mutable only if DevTools modifies them.
        #: Constructed stylesheets (new CSSStyleSheet()) are mutable immediately after creation.
        is_mutable: bool

        #: True if this stylesheet is created through new CSSStyleSheet() or imported as a
        #: CSS module script.
        is_constructed: bool

        #: Line offset of the stylesheet within the resource (zero based).
        start_line: float

        #: Column offset of the stylesheet within the resource (zero based).
        start_column: float

        #: Size of the content (in characters).
        length: float

        #: Line offset of the end of the stylesheet within the resource (zero based).
        end_line: float

        #: Column offset of the end of the stylesheet within the resource (zero based).
        end_column: float

        #: URL of source map associated with the stylesheet (if any).
        source_map_url: typing.Optional[str] = None

        #: The backend id for the owner node of the stylesheet.
        owner_node: typing.Optional[dom.BackendNodeId] = None

        #: Whether the sourceURL field value comes from the sourceURL comment.
        has_source_url: typing.Optional[bool] = None

        #: If the style sheet was loaded from a network resource, this indicates when the resource failed to load
        loading_failed: typing.Optional[bool] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['styleSheetId'] = self.style_sheet_id.to_json()
            json['frameId'] = self.frame_id.to_json()
            json['sourceURL'] = self.source_url
            json['origin'] = self.origin.to_json()
            json['title'] = self.title
            json['disabled'] = self.disabled
            json['isInline'] = self.is_inline
            json['isMutable'] = self.is_mutable
            json['isConstructed'] = self.is_constructed
            json['startLine'] = self.start_line
            json['startColumn'] = self.start_column
            json['length'] = self.length
            json['endLine'] = self.end_line
            json['endColumn'] = self.end_column
            if self.source_map_url is not None:
                json['sourceMapURL'] = self.source_map_url
            if self.owner_node is not None:
                json['ownerNode'] = self.owner_node.to_json()
            if self.has_source_url is not None:
                json['hasSourceURL'] = self.has_source_url
            if self.loading_failed is not None:
                json['loadingFailed'] = self.loading_failed
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSStyleSheetHeader:
            return cls(
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']),
                frame_id=page.FrameId.from_json(json['frameId']),
                source_url=str(json['sourceURL']),
                origin=StyleSheetOrigin.from_json(json['origin']),
                title=str(json['title']),
                disabled=bool(json['disabled']),
                is_inline=bool(json['isInline']),
                is_mutable=bool(json['isMutable']),
                is_constructed=bool(json['isConstructed']),
                start_line=float(json['startLine']),
                start_column=float(json['startColumn']),
                length=float(json['length']),
                end_line=float(json['endLine']),
                end_column=float(json['endColumn']),
                source_map_url=str(json['sourceMapURL']) if json.get('sourceMapURL', None) is not None else None,
                owner_node=dom.BackendNodeId.from_json(json['ownerNode']) if json.get('ownerNode', None) is not None else None,
                has_source_url=bool(json['hasSourceURL']) if json.get('hasSourceURL', None) is not None else None,
                loading_failed=bool(json['loadingFailed']) if json.get('loadingFailed', None) is not None else None,
            )

    @dataclass
    class CSSRule:
        '''
        CSS rule representation.
        '''
        #: Rule selector data.
        selector_list: SelectorList

        #: Parent stylesheet's origin.
        origin: StyleSheetOrigin

        #: Associated style declaration.
        style: CSSStyle

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        #: Array of selectors from ancestor style rules, sorted by distance from the current rule.
        nesting_selectors: typing.Optional[typing.List[str]] = None

        #: Media list array (for rules involving media queries). The array enumerates media queries
        #: starting with the innermost one, going outwards.
        media: typing.Optional[typing.List[CSSMedia]] = None

        #: Container query list array (for rules involving container queries).
        #: The array enumerates container queries starting with the innermost one, going outwards.
        container_queries: typing.Optional[typing.List[CSSContainerQuery]] = None

        #: @supports CSS at-rule array.
        #: The array enumerates @supports at-rules starting with the innermost one, going outwards.
        supports: typing.Optional[typing.List[CSSSupports]] = None

        #: Cascade layer array. Contains the layer hierarchy that this rule belongs to starting
        #: with the innermost layer and going outwards.
        layers: typing.Optional[typing.List[CSSLayer]] = None

        #: @scope CSS at-rule array.
        #: The array enumerates @scope at-rules starting with the innermost one, going outwards.
        scopes: typing.Optional[typing.List[CSSScope]] = None

        #: The array keeps the types of ancestor CSSRules from the innermost going outwards.
        rule_types: typing.Optional[typing.List[CSSRuleType]] = None

        #: @starting-style CSS at-rule array.
        #: The array enumerates @starting-style at-rules starting with the innermost one, going outwards.
        starting_styles: typing.Optional[typing.List[CSSStartingStyle]] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['selectorList'] = self.selector_list.to_json()
            json['origin'] = self.origin.to_json()
            json['style'] = self.style.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            if self.nesting_selectors is not None:
                json['nestingSelectors'] = [i for i in self.nesting_selectors]
            if self.media is not None:
                json['media'] = [i.to_json() for i in self.media]
            if self.container_queries is not None:
                json['containerQueries'] = [i.to_json() for i in self.container_queries]
            if self.supports is not None:
                json['supports'] = [i.to_json() for i in self.supports]
            if self.layers is not None:
                json['layers'] = [i.to_json() for i in self.layers]
            if self.scopes is not None:
                json['scopes'] = [i.to_json() for i in self.scopes]
            if self.rule_types is not None:
                json['ruleTypes'] = [i.to_json() for i in self.rule_types]
            if self.starting_styles is not None:
                json['startingStyles'] = [i.to_json() for i in self.starting_styles]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSRule:
            return cls(
                selector_list=SelectorList.from_json(json['selectorList']),
                origin=StyleSheetOrigin.from_json(json['origin']),
                style=CSSStyle.from_json(json['style']),
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
                nesting_selectors=[str(i) for i in json['nestingSelectors']] if json.get('nestingSelectors', None) is not None else None,
                media=[CSSMedia.from_json(i) for i in json['media']] if json.get('media', None) is not None else None,
                container_queries=[CSSContainerQuery.from_json(i) for i in json['containerQueries']] if json.get('containerQueries', None) is not None else None,
                supports=[CSSSupports.from_json(i) for i in json['supports']] if json.get('supports', None) is not None else None,
                layers=[CSSLayer.from_json(i) for i in json['layers']] if json.get('layers', None) is not None else None,
                scopes=[CSSScope.from_json(i) for i in json['scopes']] if json.get('scopes', None) is not None else None,
                rule_types=[CSSRuleType.from_json(i) for i in json['ruleTypes']] if json.get('ruleTypes', None) is not None else None,
                starting_styles=[CSSStartingStyle.from_json(i) for i in json['startingStyles']] if json.get('startingStyles', None) is not None else None,
            )

    class CSSRuleType(enum.Enum):
        '''
        Enum indicating the type of a CSS rule, used to represent the order of a style rule's ancestors.
        This list only contains rule types that are collected during the ancestor rule collection.
        '''
        MEDIA_RULE = "MediaRule"
        SUPPORTS_RULE = "SupportsRule"
        CONTAINER_RULE = "ContainerRule"
        LAYER_RULE = "LayerRule"
        SCOPE_RULE = "ScopeRule"
        STYLE_RULE = "StyleRule"
        STARTING_STYLE_RULE = "StartingStyleRule"

        def to_json(self) -> str:
            return self.value

        @classmethod
        def from_json(cls, json: str) -> CSSRuleType:
            return cls(json)

    @dataclass
    class RuleUsage:
        '''
        CSS coverage information.
        '''
        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: StyleSheetId

        #: Offset of the start of the rule (including selector) from the beginning of the stylesheet.
        start_offset: float

        #: Offset of the end of the rule body from the beginning of the stylesheet.
        end_offset: float

        #: Indicates whether the rule was actually used by some element in the page.
        used: bool

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['styleSheetId'] = self.style_sheet_id.to_json()
            json['startOffset'] = self.start_offset
            json['endOffset'] = self.end_offset
            json['used'] = self.used
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> RuleUsage:
            return cls(
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']),
                start_offset=float(json['startOffset']),
                end_offset=float(json['endOffset']),
                used=bool(json['used']),
            )

    @dataclass
    class SourceRange:
        '''
        Text range within a resource. All numbers are zero-based.
        '''
        #: Start line of range.
        start_line: int

        #: Start column of range (inclusive).
        start_column: int

        #: End line of range
        end_line: int

        #: End column of range (exclusive).
        end_column: int

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['startLine'] = self.start_line
            json['startColumn'] = self.start_column
            json['endLine'] = self.end_line
            json['endColumn'] = self.end_column
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> SourceRange:
            return cls(
                start_line=int(json['startLine']),
                start_column=int(json['startColumn']),
                end_line=int(json['endLine']),
                end_column=int(json['endColumn']),
            )

    @dataclass
    class ShorthandEntry:
        #: Shorthand name.
        name: str

        #: Shorthand value.
        value: str

        #: Whether the property has "!important" annotation (implies ``false`` if absent).
        important: typing.Optional[bool] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['name'] = self.name
            json['value'] = self.value
            if self.important is not None:
                json['important'] = self.important
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> ShorthandEntry:
            return cls(
                name=str(json['name']),
                value=str(json['value']),
                important=bool(json['important']) if json.get('important', None) is not None else None,
            )

    @dataclass
    class CSSComputedStyleProperty:
        #: Computed style property name.
        name: str

        #: Computed style property value.
        value: str

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['name'] = self.name
            json['value'] = self.value
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSComputedStyleProperty:
            return cls(
                name=str(json['name']),
                value=str(json['value']),
            )

    @dataclass
    class ComputedStyleExtraFields:
        #: Returns whether or not this node is being rendered with base appearance,
        #: which happens when it has its appearance property set to base/base-select
        #: or it is in the subtree of an element being rendered with base appearance.
        is_appearance_base: bool

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['isAppearanceBase'] = self.is_appearance_base
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> ComputedStyleExtraFields:
            return cls(
                is_appearance_base=bool(json['isAppearanceBase']),
            )

    @dataclass
    class CSSStyle:
        '''
        CSS style representation.
        '''
        #: CSS properties in the style.
        css_properties: typing.List[CSSProperty]

        #: Computed values for all shorthands found in the style.
        shorthand_entries: typing.List[ShorthandEntry]

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        #: Style declaration text (if available).
        css_text: typing.Optional[str] = None

        #: Style declaration range in the enclosing stylesheet (if available).
        range_: typing.Optional[SourceRange] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['cssProperties'] = [i.to_json() for i in self.css_properties]
            json['shorthandEntries'] = [i.to_json() for i in self.shorthand_entries]
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            if self.css_text is not None:
                json['cssText'] = self.css_text
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSStyle:
            return cls(
                css_properties=[CSSProperty.from_json(i) for i in json['cssProperties']],
                shorthand_entries=[ShorthandEntry.from_json(i) for i in json['shorthandEntries']],
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
                css_text=str(json['cssText']) if json.get('cssText', None) is not None else None,
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
            )

    @dataclass
    class CSSProperty:
        '''
        CSS property declaration data.
        '''
        #: The property name.
        name: str

        #: The property value.
        value: str

        #: Whether the property has "!important" annotation (implies ``false`` if absent).
        important: typing.Optional[bool] = None

        #: Whether the property is implicit (implies ``false`` if absent).
        implicit: typing.Optional[bool] = None

        #: The full property text as specified in the style.
        text: typing.Optional[str] = None

        #: Whether the property is understood by the browser (implies ``true`` if absent).
        parsed_ok: typing.Optional[bool] = None

        #: Whether the property is disabled by the user (present for source-based properties only).
        disabled: typing.Optional[bool] = None

        #: The entire property range in the enclosing style declaration (if available).
        range_: typing.Optional[SourceRange] = None

        #: Parsed longhand components of this property if it is a shorthand.
        #: This field will be empty if the given property is not a shorthand.
        longhand_properties: typing.Optional[typing.List[CSSProperty]] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['name'] = self.name
            json['value'] = self.value
            if self.important is not None:
                json['important'] = self.important
            if self.implicit is not None:
                json['implicit'] = self.implicit
            if self.text is not None:
                json['text'] = self.text
            if self.parsed_ok is not None:
                json['parsedOk'] = self.parsed_ok
            if self.disabled is not None:
                json['disabled'] = self.disabled
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.longhand_properties is not None:
                json['longhandProperties'] = [i.to_json() for i in self.longhand_properties]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSProperty:
            return cls(
                name=str(json['name']),
                value=str(json['value']),
                important=bool(json['important']) if json.get('important', None) is not None else None,
                implicit=bool(json['implicit']) if json.get('implicit', None) is not None else None,
                text=str(json['text']) if json.get('text', None) is not None else None,
                parsed_ok=bool(json['parsedOk']) if json.get('parsedOk', None) is not None else None,
                disabled=bool(json['disabled']) if json.get('disabled', None) is not None else None,
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                longhand_properties=[CSSProperty.from_json(i) for i in json['longhandProperties']] if json.get('longhandProperties', None) is not None else None,
            )

    @dataclass
    class CSSMedia:
        '''
        CSS media rule descriptor.
        '''
        #: Media query text.
        text: str

        #: Source of the media query: "mediaRule" if specified by a @media rule, "importRule" if
        #: specified by an @import rule, "linkedSheet" if specified by a "media" attribute in a linked
        #: stylesheet's LINK tag, "inlineSheet" if specified by a "media" attribute in an inline
        #: stylesheet's STYLE tag.
        source: str

        #: URL of the document containing the media query description.
        source_url: typing.Optional[str] = None

        #: The associated rule (@media or @import) header range in the enclosing stylesheet (if
        #: available).
        range_: typing.Optional[SourceRange] = None

        #: Identifier of the stylesheet containing this object (if exists).
        style_sheet_id: typing.Optional[StyleSheetId] = None

        #: Array of media queries.
        media_list: typing.Optional[typing.List[MediaQuery]] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['text'] = self.text
            json['source'] = self.source
            if self.source_url is not None:
                json['sourceURL'] = self.source_url
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            if self.media_list is not None:
                json['mediaList'] = [i.to_json() for i in self.media_list]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSMedia:
            return cls(
                text=str(json['text']),
                source=str(json['source']),
                source_url=str(json['sourceURL']) if json.get('sourceURL', None) is not None else None,
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
                media_list=[MediaQuery.from_json(i) for i in json['mediaList']] if json.get('mediaList', None) is not None else None,
            )

    @dataclass
    class MediaQuery:
        '''
        Media query descriptor.
        '''
        #: Array of media query expressions.
        expressions: typing.List[MediaQueryExpression]

        #: Whether the media query condition is satisfied.
        active: bool

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['expressions'] = [i.to_json() for i in self.expressions]
            json['active'] = self.active
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> MediaQuery:
            return cls(
                expressions=[MediaQueryExpression.from_json(i) for i in json['expressions']],
                active=bool(json['active']),
            )

    @dataclass
    class MediaQueryExpression:
        '''
        Media query expression descriptor.
        '''
        #: Media query expression value.
        value: float

        #: Media query expression units.
        unit: str

        #: Media query expression feature.
        feature: str

        #: The associated range of the value text in the enclosing stylesheet (if available).
        value_range: typing.Optional[SourceRange] = None

        #: Computed length of media query expression (if applicable).
        computed_length: typing.Optional[float] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['value'] = self.value
            json['unit'] = self.unit
            json['feature'] = self.feature
            if self.value_range is not None:
                json['valueRange'] = self.value_range.to_json()
            if self.computed_length is not None:
                json['computedLength'] = self.computed_length
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> MediaQueryExpression:
            return cls(
                value=float(json['value']),
                unit=str(json['unit']),
                feature=str(json['feature']),
                value_range=SourceRange.from_json(json['valueRange']) if json.get('valueRange', None) is not None else None,
                computed_length=float(json['computedLength']) if json.get('computedLength', None) is not None else None,
            )

    @dataclass
    class CSSContainerQuery:
        '''
        CSS container query rule descriptor.
        '''
        #: Container query text.
        text: str

        #: The associated rule header range in the enclosing stylesheet (if
        #: available).
        range_: typing.Optional[SourceRange] = None

        #: Identifier of the stylesheet containing this object (if exists).
        style_sheet_id: typing.Optional[StyleSheetId] = None

        #: Optional name for the container.
        name: typing.Optional[str] = None

        #: Optional physical axes queried for the container.
        physical_axes: typing.Optional[dom.PhysicalAxes] = None

        #: Optional logical axes queried for the container.
        logical_axes: typing.Optional[dom.LogicalAxes] = None

        #: true if the query contains scroll-state() queries.
        queries_scroll_state: typing.Optional[bool] = None

        #: true if the query contains anchored() queries.
        queries_anchored: typing.Optional[bool] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['text'] = self.text
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            if self.name is not None:
                json['name'] = self.name
            if self.physical_axes is not None:
                json['physicalAxes'] = self.physical_axes.to_json()
            if self.logical_axes is not None:
                json['logicalAxes'] = self.logical_axes.to_json()
            if self.queries_scroll_state is not None:
                json['queriesScrollState'] = self.queries_scroll_state
            if self.queries_anchored is not None:
                json['queriesAnchored'] = self.queries_anchored
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSContainerQuery:
            return cls(
                text=str(json['text']),
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
                name=str(json['name']) if json.get('name', None) is not None else None,
                physical_axes=dom.PhysicalAxes.from_json(json['physicalAxes']) if json.get('physicalAxes', None) is not None else None,
                logical_axes=dom.LogicalAxes.from_json(json['logicalAxes']) if json.get('logicalAxes', None) is not None else None,
                queries_scroll_state=bool(json['queriesScrollState']) if json.get('queriesScrollState', None) is not None else None,
                queries_anchored=bool(json['queriesAnchored']) if json.get('queriesAnchored', None) is not None else None,
            )

    @dataclass
    class CSSSupports:
        '''
        CSS Supports at-rule descriptor.
        '''
        #: Supports rule text.
        text: str

        #: Whether the supports condition is satisfied.
        active: bool

        #: The associated rule header range in the enclosing stylesheet (if
        #: available).
        range_: typing.Optional[SourceRange] = None

        #: Identifier of the stylesheet containing this object (if exists).
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['text'] = self.text
            json['active'] = self.active
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSSupports:
            return cls(
                text=str(json['text']),
                active=bool(json['active']),
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSScope:
        '''
        CSS Scope at-rule descriptor.
        '''
        #: Scope rule text.
        text: str

        #: The associated rule header range in the enclosing stylesheet (if
        #: available).
        range_: typing.Optional[SourceRange] = None

        #: Identifier of the stylesheet containing this object (if exists).
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['text'] = self.text
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSScope:
            return cls(
                text=str(json['text']),
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSLayer:
        '''
        CSS Layer at-rule descriptor.
        '''
        #: Layer name.
        text: str

        #: The associated rule header range in the enclosing stylesheet (if
        #: available).
        range_: typing.Optional[SourceRange] = None

        #: Identifier of the stylesheet containing this object (if exists).
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['text'] = self.text
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSLayer:
            return cls(
                text=str(json['text']),
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSStartingStyle:
        '''
        CSS Starting Style at-rule descriptor.
        '''
        #: The associated rule header range in the enclosing stylesheet (if
        #: available).
        range_: typing.Optional[SourceRange] = None

        #: Identifier of the stylesheet containing this object (if exists).
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            if self.range_ is not None:
                json['range'] = self.range_.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSStartingStyle:
            return cls(
                range_=SourceRange.from_json(json['range']) if json.get('range', None) is not None else None,
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSLayerData:
        '''
        CSS Layer data.
        '''
        #: Layer name.
        name: str

        #: Layer order. The order determines the order of the layer in the cascade order.
        #: A higher number has higher priority in the cascade order.
        order: float

        #: Direct sub-layers
        sub_layers: typing.Optional[typing.List[CSSLayerData]] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['name'] = self.name
            json['order'] = self.order
            if self.sub_layers is not None:
                json['subLayers'] = [i.to_json() for i in self.sub_layers]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSLayerData:
            return cls(
                name=str(json['name']),
                order=float(json['order']),
                sub_layers=[CSSLayerData.from_json(i) for i in json['subLayers']] if json.get('subLayers', None) is not None else None,
            )

    @dataclass
    class PlatformFontUsage:
        '''
        Information about amount of glyphs that were rendered with given font.
        '''
        #: Font's family name reported by platform.
        family_name: str

        #: Font's PostScript name reported by platform.
        post_script_name: str

        #: Indicates if the font was downloaded or resolved locally.
        is_custom_font: bool

        #: Amount of glyphs that were rendered with this font.
        glyph_count: float

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['familyName'] = self.family_name
            json['postScriptName'] = self.post_script_name
            json['isCustomFont'] = self.is_custom_font
            json['glyphCount'] = self.glyph_count
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> PlatformFontUsage:
            return cls(
                family_name=str(json['familyName']),
                post_script_name=str(json['postScriptName']),
                is_custom_font=bool(json['isCustomFont']),
                glyph_count=float(json['glyphCount']),
            )

    @dataclass
    class FontVariationAxis:
        '''
        Information about font variation axes for variable fonts
        '''
        #: The font-variation-setting tag (a.k.a. "axis tag").
        tag: str

        #: Human-readable variation name in the default language (normally, "en").
        name: str

        #: The minimum value (inclusive) the font supports for this tag.
        min_value: float

        #: The maximum value (inclusive) the font supports for this tag.
        max_value: float

        #: The default value.
        default_value: float

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['tag'] = self.tag
            json['name'] = self.name
            json['minValue'] = self.min_value
            json['maxValue'] = self.max_value
            json['defaultValue'] = self.default_value
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> FontVariationAxis:
            return cls(
                tag=str(json['tag']),
                name=str(json['name']),
                min_value=float(json['minValue']),
                max_value=float(json['maxValue']),
                default_value=float(json['defaultValue']),
            )

    @dataclass
    class FontFace:
        '''
        Properties of a web font: https://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#font-descriptions
        and additional information such as platformFontFamily and fontVariationAxes.
        '''
        #: The font-family.
        font_family: str

        #: The font-style.
        font_style: str

        #: The font-variant.
        font_variant: str

        #: The font-weight.
        font_weight: str

        #: The font-stretch.
        font_stretch: str

        #: The font-display.
        font_display: str

        #: The unicode-range.
        unicode_range: str

        #: The src.
        src: str

        #: The resolved platform font family
        platform_font_family: str

        #: Available variation settings (a.k.a. "axes").
        font_variation_axes: typing.Optional[typing.List[FontVariationAxis]] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['fontFamily'] = self.font_family
            json['fontStyle'] = self.font_style
            json['fontVariant'] = self.font_variant
            json['fontWeight'] = self.font_weight
            json['fontStretch'] = self.font_stretch
            json['fontDisplay'] = self.font_display
            json['unicodeRange'] = self.unicode_range
            json['src'] = self.src
            json['platformFontFamily'] = self.platform_font_family
            if self.font_variation_axes is not None:
                json['fontVariationAxes'] = [i.to_json() for i in self.font_variation_axes]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> FontFace:
            return cls(
                font_family=str(json['fontFamily']),
                font_style=str(json['fontStyle']),
                font_variant=str(json['fontVariant']),
                font_weight=str(json['fontWeight']),
                font_stretch=str(json['fontStretch']),
                font_display=str(json['fontDisplay']),
                unicode_range=str(json['unicodeRange']),
                src=str(json['src']),
                platform_font_family=str(json['platformFontFamily']),
                font_variation_axes=[FontVariationAxis.from_json(i) for i in json['fontVariationAxes']] if json.get('fontVariationAxes', None) is not None else None,
            )

    @dataclass
    class CSSTryRule:
        '''
        CSS try rule representation.
        '''
        #: Parent stylesheet's origin.
        origin: StyleSheetOrigin

        #: Associated style declaration.
        style: CSSStyle

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['origin'] = self.origin.to_json()
            json['style'] = self.style.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSTryRule:
            return cls(
                origin=StyleSheetOrigin.from_json(json['origin']),
                style=CSSStyle.from_json(json['style']),
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSPositionTryRule:
        '''
        CSS @position-try rule representation.
        '''
        #: The prelude dashed-ident name
        name: Value

        #: Parent stylesheet's origin.
        origin: StyleSheetOrigin

        #: Associated style declaration.
        style: CSSStyle

        active: bool

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['name'] = self.name.to_json()
            json['origin'] = self.origin.to_json()
            json['style'] = self.style.to_json()
            json['active'] = self.active
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSPositionTryRule:
            return cls(
                name=Value.from_json(json['name']),
                origin=StyleSheetOrigin.from_json(json['origin']),
                style=CSSStyle.from_json(json['style']),
                active=bool(json['active']),
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSKeyframesRule:
        '''
        CSS keyframes rule representation.
        '''
        #: Animation name.
        animation_name: Value

        #: List of keyframes.
        keyframes: typing.List[CSSKeyframeRule]

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['animationName'] = self.animation_name.to_json()
            json['keyframes'] = [i.to_json() for i in self.keyframes]
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSKeyframesRule:
            return cls(
                animation_name=Value.from_json(json['animationName']),
                keyframes=[CSSKeyframeRule.from_json(i) for i in json['keyframes']],
            )

    @dataclass
    class CSSPropertyRegistration:
        '''
        Representation of a custom property registration through CSS.registerProperty
        '''
        property_name: str

        inherits: bool

        syntax: str

        initial_value: typing.Optional[Value] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['propertyName'] = self.property_name
            json['inherits'] = self.inherits
            json['syntax'] = self.syntax
            if self.initial_value is not None:
                json['initialValue'] = self.initial_value.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSPropertyRegistration:
            return cls(
                property_name=str(json['propertyName']),
                inherits=bool(json['inherits']),
                syntax=str(json['syntax']),
                initial_value=Value.from_json(json['initialValue']) if json.get('initialValue', None) is not None else None,
            )

    @dataclass
    class CSSFontPaletteValuesRule:
        '''
        CSS font-palette-values rule representation.
        '''
        #: Parent stylesheet's origin.
        origin: StyleSheetOrigin

        #: Associated font palette name.
        font_palette_name: Value

        #: Associated style declaration.
        style: CSSStyle

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['origin'] = self.origin.to_json()
            json['fontPaletteName'] = self.font_palette_name.to_json()
            json['style'] = self.style.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSFontPaletteValuesRule:
            return cls(
                origin=StyleSheetOrigin.from_json(json['origin']),
                font_palette_name=Value.from_json(json['fontPaletteName']),
                style=CSSStyle.from_json(json['style']),
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSPropertyRule:
        '''
        CSS property at-rule representation.
        '''
        #: Parent stylesheet's origin.
        origin: StyleSheetOrigin

        #: Associated property name.
        property_name: Value

        #: Associated style declaration.
        style: CSSStyle

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['origin'] = self.origin.to_json()
            json['propertyName'] = self.property_name.to_json()
            json['style'] = self.style.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSPropertyRule:
            return cls(
                origin=StyleSheetOrigin.from_json(json['origin']),
                property_name=Value.from_json(json['propertyName']),
                style=CSSStyle.from_json(json['style']),
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSFunctionParameter:
        '''
        CSS function argument representation.
        '''
        #: The parameter name.
        name: str

        #: The parameter type.
        type_: str

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['name'] = self.name
            json['type'] = self.type_
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSFunctionParameter:
            return cls(
                name=str(json['name']),
                type_=str(json['type']),
            )

    @dataclass
    class CSSFunctionConditionNode:
        '''
        CSS function conditional block representation.
        '''
        #: Block body.
        children: typing.List[CSSFunctionNode]

        #: The condition text.
        condition_text: str

        #: Media query for this conditional block. Only one type of condition should be set.
        media: typing.Optional[CSSMedia] = None

        #: Container query for this conditional block. Only one type of condition should be set.
        container_queries: typing.Optional[CSSContainerQuery] = None

        #: @supports CSS at-rule condition. Only one type of condition should be set.
        supports: typing.Optional[CSSSupports] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['children'] = [i.to_json() for i in self.children]
            json['conditionText'] = self.condition_text
            if self.media is not None:
                json['media'] = self.media.to_json()
            if self.container_queries is not None:
                json['containerQueries'] = self.container_queries.to_json()
            if self.supports is not None:
                json['supports'] = self.supports.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSFunctionConditionNode:
            return cls(
                children=[CSSFunctionNode.from_json(i) for i in json['children']],
                condition_text=str(json['conditionText']),
                media=CSSMedia.from_json(json['media']) if json.get('media', None) is not None else None,
                container_queries=CSSContainerQuery.from_json(json['containerQueries']) if json.get('containerQueries', None) is not None else None,
                supports=CSSSupports.from_json(json['supports']) if json.get('supports', None) is not None else None,
            )

    @dataclass
    class CSSFunctionNode:
        '''
        Section of the body of a CSS function rule.
        '''
        #: A conditional block. If set, style should not be set.
        condition: typing.Optional[CSSFunctionConditionNode] = None

        #: Values set by this node. If set, condition should not be set.
        style: typing.Optional[CSSStyle] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            if self.condition is not None:
                json['condition'] = self.condition.to_json()
            if self.style is not None:
                json['style'] = self.style.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSFunctionNode:
            return cls(
                condition=CSSFunctionConditionNode.from_json(json['condition']) if json.get('condition', None) is not None else None,
                style=CSSStyle.from_json(json['style']) if json.get('style', None) is not None else None,
            )

    @dataclass
    class CSSFunctionRule:
        '''
        CSS function at-rule representation.
        '''
        #: Name of the function.
        name: Value

        #: Parent stylesheet's origin.
        origin: StyleSheetOrigin

        #: List of parameters.
        parameters: typing.List[CSSFunctionParameter]

        #: Function body.
        children: typing.List[CSSFunctionNode]

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['name'] = self.name.to_json()
            json['origin'] = self.origin.to_json()
            json['parameters'] = [i.to_json() for i in self.parameters]
            json['children'] = [i.to_json() for i in self.children]
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSFunctionRule:
            return cls(
                name=Value.from_json(json['name']),
                origin=StyleSheetOrigin.from_json(json['origin']),
                parameters=[CSSFunctionParameter.from_json(i) for i in json['parameters']],
                children=[CSSFunctionNode.from_json(i) for i in json['children']],
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class CSSKeyframeRule:
        '''
        CSS keyframe rule representation.
        '''
        #: Parent stylesheet's origin.
        origin: StyleSheetOrigin

        #: Associated key text.
        key_text: Value

        #: Associated style declaration.
        style: CSSStyle

        #: The css style sheet identifier (absent for user agent stylesheet and user-specified
        #: stylesheet rules) this rule came from.
        style_sheet_id: typing.Optional[StyleSheetId] = None

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['origin'] = self.origin.to_json()
            json['keyText'] = self.key_text.to_json()
            json['style'] = self.style.to_json()
            if self.style_sheet_id is not None:
                json['styleSheetId'] = self.style_sheet_id.to_json()
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> CSSKeyframeRule:
            return cls(
                origin=StyleSheetOrigin.from_json(json['origin']),
                key_text=Value.from_json(json['keyText']),
                style=CSSStyle.from_json(json['style']),
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']) if json.get('styleSheetId', None) is not None else None,
            )

    @dataclass
    class StyleDeclarationEdit:
        '''
        A descriptor of operation to mutate style declaration text.
        '''
        #: The css style sheet identifier.
        style_sheet_id: StyleSheetId

        #: The range of the style text in the enclosing stylesheet.
        range_: SourceRange

        #: New style text.
        text: str

        def to_json(self) -> T_JSON_DICT:
            json: T_JSON_DICT = dict()
            json['styleSheetId'] = self.style_sheet_id.to_json()
            json['range'] = self.range_.to_json()
            json['text'] = self.text
            return json

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> StyleDeclarationEdit:
            return cls(
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId']),
                range_=SourceRange.from_json(json['range']),
                text=str(json['text']),
            )

    def add_rule(
            style_sheet_id: StyleSheetId,
            rule_text: str,
            location: SourceRange,
            node_for_property_syntax_validation: typing.Optional[dom.NodeId] = None
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,CSSRule]:
        '''
        Inserts a new rule with the given ``ruleText`` in a stylesheet with given ``styleSheetId``, at the
        position specified by ``location``.

        :param style_sheet_id: The css style sheet identifier where a new rule should be inserted.
        :param rule_text: The text of a new rule.
        :param location: Text position of a new rule in the target style sheet.
        :param node_for_property_syntax_validation: **(EXPERIMENTAL)** *(Optional)* NodeId for the DOM node in whose context custom property declarations for registered properties should be validated. If omitted, declarations in the new rule text can only be validated statically, which may produce incorrect results if the declaration contains a var() for example.
        :returns: The newly created rule.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['ruleText'] = rule_text
        params['location'] = location.to_json()
        if node_for_property_syntax_validation is not None:
            params['nodeForPropertySyntaxValidation'] = node_for_property_syntax_validation.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.addRule',
            'params': params,
        }
        json = yield cmd_dict
        return CSSRule.from_json(json['rule'])

    def collect_class_names(
            style_sheet_id: StyleSheetId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[str]]:
        '''
        Returns all class names from specified stylesheet.

        :param style_sheet_id:
        :returns: Class name list.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.collectClassNames',
            'params': params,
        }
        json = yield cmd_dict
        return [str(i) for i in json['classNames']]

    def create_style_sheet(
            frame_id: page.FrameId,
            force: typing.Optional[bool] = None
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,StyleSheetId]:
        '''
        Creates a new special "via-inspector" stylesheet in the frame with given ``frameId``.

        :param frame_id: Identifier of the frame where "via-inspector" stylesheet should be created.
        :param force: *(Optional)* If true, creates a new stylesheet for every call. If false, returns a stylesheet previously created by a call with force=false for the frame's document if it exists or creates a new stylesheet (default: false).
        :returns: Identifier of the created "via-inspector" stylesheet.
        '''
        params: T_JSON_DICT = dict()
        params['frameId'] = frame_id.to_json()
        if force is not None:
            params['force'] = force
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.createStyleSheet',
            'params': params,
        }
        json = yield cmd_dict
        return StyleSheetId.from_json(json['styleSheetId'])

    def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Disables the CSS agent for the given page.
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.disable',
        }
        json = yield cmd_dict

    def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Enables the CSS agent for the given page. Clients should not assume that the CSS agent has been
        enabled until the result of this command is received.
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.enable',
        }
        json = yield cmd_dict

    def force_pseudo_state(
            node_id: dom.NodeId,
            forced_pseudo_classes: typing.List[str]
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Ensures that the given node will have specified pseudo-classes whenever its style is computed by
        the browser.

        :param node_id: The element id for which to force the pseudo state.
        :param forced_pseudo_classes: Element pseudo classes to force when computing the element's style.
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        params['forcedPseudoClasses'] = [i for i in forced_pseudo_classes]
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.forcePseudoState',
            'params': params,
        }
        json = yield cmd_dict

    def force_starting_style(
            node_id: dom.NodeId,
            forced: bool
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Ensures that the given node is in its starting-style state.

        :param node_id: The element id for which to force the starting-style state.
        :param forced: Boolean indicating if this is on or off.
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        params['forced'] = forced
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.forceStartingStyle',
            'params': params,
        }
        json = yield cmd_dict

    def get_background_colors(
            node_id: dom.NodeId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[typing.List[str]], typing.Optional[str], typing.Optional[str]]]:
        '''
        :param node_id: Id of the node to get background colors for.
        :returns: A tuple with the following items:

            0. **backgroundColors** - *(Optional)* The range of background colors behind this element, if it contains any visible text. If no visible text is present, this will be undefined. In the case of a flat background color, this will consist of simply that color. In the case of a gradient, this will consist of each of the color stops. For anything more complicated, this will be an empty array. Images will be ignored (as if the image had failed to load).
            1. **computedFontSize** - *(Optional)* The computed font size for this node, as a CSS computed value string (e.g. '12px').
            2. **computedFontWeight** - *(Optional)* The computed font weight for this node, as a CSS computed value string (e.g. 'normal' or '100').
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getBackgroundColors',
            'params': params,
        }
        json = yield cmd_dict
        return (
            [str(i) for i in json['backgroundColors']] if json.get('backgroundColors', None) is not None else None,
            str(json['computedFontSize']) if json.get('computedFontSize', None) is not None else None,
            str(json['computedFontWeight']) if json.get('computedFontWeight', None) is not None else None
        )

    def get_computed_style_for_node(
            node_id: dom.NodeId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.List[CSSComputedStyleProperty], ComputedStyleExtraFields]]:
        '''
        Returns the computed style for a DOM node identified by ``nodeId``.

        :param node_id:
        :returns: A tuple with the following items:

            0. **computedStyle** - Computed style for the specified DOM node.
            1. **extraFields** - A list of non-standard "extra fields" which blink stores alongside each computed style.
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getComputedStyleForNode',
            'params': params,
        }
        json = yield cmd_dict
        return (
            [CSSComputedStyleProperty.from_json(i) for i in json['computedStyle']],
            ComputedStyleExtraFields.from_json(json['extraFields'])
        )

    def resolve_values(
            values: typing.List[str],
            node_id: dom.NodeId,
            property_name: typing.Optional[str] = None,
            pseudo_type: typing.Optional[dom.PseudoType] = None,
            pseudo_identifier: typing.Optional[str] = None
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[str]]:
        '''
        Resolve the specified values in the context of the provided element.
        For example, a value of '1em' is evaluated according to the computed
        'font-size' of the element and a value 'calc(1px + 2px)' will be
        resolved to '3px'.
        If the ``propertyName`` was specified the ``values`` are resolved as if
        they were property's declaration. If a value cannot be parsed according
        to the provided property syntax, the value is parsed using combined
        syntax as if null ``propertyName`` was provided. If the value cannot be
        resolved even then, return the provided value without any changes.

        **EXPERIMENTAL**

        :param values: Cascade-dependent keywords (revert/revert-layer) do not work.
        :param node_id: Id of the node in whose context the expression is evaluated
        :param property_name: *(Optional)* Only longhands and custom property names are accepted.
        :param pseudo_type: *(Optional)* Pseudo element type, only works for pseudo elements that generate elements in the tree, such as ::before and ::after.
        :param pseudo_identifier: *(Optional)* Pseudo element custom ident.
        :returns:
        '''
        params: T_JSON_DICT = dict()
        params['values'] = [i for i in values]
        params['nodeId'] = node_id.to_json()
        if property_name is not None:
            params['propertyName'] = property_name
        if pseudo_type is not None:
            params['pseudoType'] = pseudo_type.to_json()
        if pseudo_identifier is not None:
            params['pseudoIdentifier'] = pseudo_identifier
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.resolveValues',
            'params': params,
        }
        json = yield cmd_dict
        return [str(i) for i in json['results']]

    def get_longhand_properties(
            shorthand_name: str,
            value: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[CSSProperty]]:
        '''

        **EXPERIMENTAL**

        :param shorthand_name:
        :param value:
        :returns:
        '''
        params: T_JSON_DICT = dict()
        params['shorthandName'] = shorthand_name
        params['value'] = value
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getLonghandProperties',
            'params': params,
        }
        json = yield cmd_dict
        return [CSSProperty.from_json(i) for i in json['longhandProperties']]

    def get_inline_styles_for_node(
            node_id: dom.NodeId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[CSSStyle], typing.Optional[CSSStyle]]]:
        '''
        Returns the styles defined inline (explicitly in the "style" attribute and implicitly, using DOM
        attributes) for a DOM node identified by ``nodeId``.

        :param node_id:
        :returns: A tuple with the following items:

            0. **inlineStyle** - *(Optional)* Inline style for the specified DOM node.
            1. **attributesStyle** - *(Optional)* Attribute-defined element style (e.g. resulting from "width=20 height=100%").
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getInlineStylesForNode',
            'params': params,
        }
        json = yield cmd_dict
        return (
            CSSStyle.from_json(json['inlineStyle']) if json.get('inlineStyle', None) is not None else None,
            CSSStyle.from_json(json['attributesStyle']) if json.get('attributesStyle', None) is not None else None
        )

    def get_animated_styles_for_node(
            node_id: dom.NodeId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[typing.List[CSSAnimationStyle]], typing.Optional[CSSStyle], typing.Optional[typing.List[InheritedAnimatedStyleEntry]]]]:
        '''
        Returns the styles coming from animations & transitions
        including the animation & transition styles coming from inheritance chain.

        **EXPERIMENTAL**

        :param node_id:
        :returns: A tuple with the following items:

            0. **animationStyles** - *(Optional)* Styles coming from animations.
            1. **transitionsStyle** - *(Optional)* Style coming from transitions.
            2. **inherited** - *(Optional)* Inherited style entries for animationsStyle and transitionsStyle from the inheritance chain of the element.
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getAnimatedStylesForNode',
            'params': params,
        }
        json = yield cmd_dict
        return (
            [CSSAnimationStyle.from_json(i) for i in json['animationStyles']] if json.get('animationStyles', None) is not None else None,
            CSSStyle.from_json(json['transitionsStyle']) if json.get('transitionsStyle', None) is not None else None,
            [InheritedAnimatedStyleEntry.from_json(i) for i in json['inherited']] if json.get('inherited', None) is not None else None
        )

    def get_matched_styles_for_node(
            node_id: dom.NodeId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.Optional[CSSStyle], typing.Optional[CSSStyle], typing.Optional[typing.List[RuleMatch]], typing.Optional[typing.List[PseudoElementMatches]], typing.Optional[typing.List[InheritedStyleEntry]], typing.Optional[typing.List[InheritedPseudoElementMatches]], typing.Optional[typing.List[CSSKeyframesRule]], typing.Optional[typing.List[CSSPositionTryRule]], typing.Optional[int], typing.Optional[typing.List[CSSPropertyRule]], typing.Optional[typing.List[CSSPropertyRegistration]], typing.Optional[CSSFontPaletteValuesRule], typing.Optional[dom.NodeId], typing.Optional[typing.List[CSSFunctionRule]]]]:
        '''
        Returns requested styles for a DOM node identified by ``nodeId``.

        :param node_id:
        :returns: A tuple with the following items:

            0. **inlineStyle** - *(Optional)* Inline style for the specified DOM node.
            1. **attributesStyle** - *(Optional)* Attribute-defined element style (e.g. resulting from "width=20 height=100%").
            2. **matchedCSSRules** - *(Optional)* CSS rules matching this node, from all applicable stylesheets.
            3. **pseudoElements** - *(Optional)* Pseudo style matches for this node.
            4. **inherited** - *(Optional)* A chain of inherited styles (from the immediate node parent up to the DOM tree root).
            5. **inheritedPseudoElements** - *(Optional)* A chain of inherited pseudo element styles (from the immediate node parent up to the DOM tree root).
            6. **cssKeyframesRules** - *(Optional)* A list of CSS keyframed animations matching this node.
            7. **cssPositionTryRules** - *(Optional)* A list of CSS @position-try rules matching this node, based on the position-try-fallbacks property.
            8. **activePositionFallbackIndex** - *(Optional)* Index of the active fallback in the applied position-try-fallback property, will not be set if there is no active position-try fallback.
            9. **cssPropertyRules** - *(Optional)* A list of CSS at-property rules matching this node.
            10. **cssPropertyRegistrations** - *(Optional)* A list of CSS property registrations matching this node.
            11. **cssFontPaletteValuesRule** - *(Optional)* A font-palette-values rule matching this node.
            12. **parentLayoutNodeId** - *(Optional)* Id of the first parent element that does not have display: contents.
            13. **cssFunctionRules** - *(Optional)* A list of CSS at-function rules referenced by styles of this node.
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getMatchedStylesForNode',
            'params': params,
        }
        json = yield cmd_dict
        return (
            CSSStyle.from_json(json['inlineStyle']) if json.get('inlineStyle', None) is not None else None,
            CSSStyle.from_json(json['attributesStyle']) if json.get('attributesStyle', None) is not None else None,
            [RuleMatch.from_json(i) for i in json['matchedCSSRules']] if json.get('matchedCSSRules', None) is not None else None,
            [PseudoElementMatches.from_json(i) for i in json['pseudoElements']] if json.get('pseudoElements', None) is not None else None,
            [InheritedStyleEntry.from_json(i) for i in json['inherited']] if json.get('inherited', None) is not None else None,
            [InheritedPseudoElementMatches.from_json(i) for i in json['inheritedPseudoElements']] if json.get('inheritedPseudoElements', None) is not None else None,
            [CSSKeyframesRule.from_json(i) for i in json['cssKeyframesRules']] if json.get('cssKeyframesRules', None) is not None else None,
            [CSSPositionTryRule.from_json(i) for i in json['cssPositionTryRules']] if json.get('cssPositionTryRules', None) is not None else None,
            int(json['activePositionFallbackIndex']) if json.get('activePositionFallbackIndex', None) is not None else None,
            [CSSPropertyRule.from_json(i) for i in json['cssPropertyRules']] if json.get('cssPropertyRules', None) is not None else None,
            [CSSPropertyRegistration.from_json(i) for i in json['cssPropertyRegistrations']] if json.get('cssPropertyRegistrations', None) is not None else None,
            CSSFontPaletteValuesRule.from_json(json['cssFontPaletteValuesRule']) if json.get('cssFontPaletteValuesRule', None) is not None else None,
            dom.NodeId.from_json(json['parentLayoutNodeId']) if json.get('parentLayoutNodeId', None) is not None else None,
            [CSSFunctionRule.from_json(i) for i in json['cssFunctionRules']] if json.get('cssFunctionRules', None) is not None else None
        )

    def get_environment_variables() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,dict]:
        '''
        Returns the values of the default UA-defined environment variables used in env()

        **EXPERIMENTAL**

        :returns:
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getEnvironmentVariables',
        }
        json = yield cmd_dict
        return dict(json['environmentVariables'])

    def get_media_queries() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[CSSMedia]]:
        '''
        Returns all media queries parsed by the rendering engine.

        :returns:
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getMediaQueries',
        }
        json = yield cmd_dict
        return [CSSMedia.from_json(i) for i in json['medias']]

    def get_platform_fonts_for_node(
            node_id: dom.NodeId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[PlatformFontUsage]]:
        '''
        Requests information about platform fonts which we used to render child TextNodes in the given
        node.

        :param node_id:
        :returns: Usage statistics for every employed platform font.
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getPlatformFontsForNode',
            'params': params,
        }
        json = yield cmd_dict
        return [PlatformFontUsage.from_json(i) for i in json['fonts']]

    def get_style_sheet_text(
            style_sheet_id: StyleSheetId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,str]:
        '''
        Returns the current textual content for a stylesheet.

        :param style_sheet_id:
        :returns: The stylesheet text.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getStyleSheetText',
            'params': params,
        }
        json = yield cmd_dict
        return str(json['text'])

    def get_layers_for_node(
            node_id: dom.NodeId
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,CSSLayerData]:
        '''
        Returns all layers parsed by the rendering engine for the tree scope of a node.
        Given a DOM element identified by nodeId, getLayersForNode returns the root
        layer for the nearest ancestor document or shadow root. The layer root contains
        the full layer tree for the tree scope and their ordering.

        **EXPERIMENTAL**

        :param node_id:
        :returns:
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getLayersForNode',
            'params': params,
        }
        json = yield cmd_dict
        return CSSLayerData.from_json(json['rootLayer'])

    def get_location_for_selector(
            style_sheet_id: StyleSheetId,
            selector_text: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[SourceRange]]:
        '''
        Given a CSS selector text and a style sheet ID, getLocationForSelector
        returns an array of locations of the CSS selector in the style sheet.

        **EXPERIMENTAL**

        :param style_sheet_id:
        :param selector_text:
        :returns:
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['selectorText'] = selector_text
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.getLocationForSelector',
            'params': params,
        }
        json = yield cmd_dict
        return [SourceRange.from_json(i) for i in json['ranges']]

    def track_computed_style_updates_for_node(
            node_id: typing.Optional[dom.NodeId] = None
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Starts tracking the given node for the computed style updates
        and whenever the computed style is updated for node, it queues
        a ``computedStyleUpdated`` event with throttling.
        There can only be 1 node tracked for computed style updates
        so passing a new node id removes tracking from the previous node.
        Pass ``undefined`` to disable tracking.

        **EXPERIMENTAL**

        :param node_id: *(Optional)*
        '''
        params: T_JSON_DICT = dict()
        if node_id is not None:
            params['nodeId'] = node_id.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.trackComputedStyleUpdatesForNode',
            'params': params,
        }
        json = yield cmd_dict

    def track_computed_style_updates(
            properties_to_track: typing.List[CSSComputedStyleProperty]
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Starts tracking the given computed styles for updates. The specified array of properties
        replaces the one previously specified. Pass empty array to disable tracking.
        Use takeComputedStyleUpdates to retrieve the list of nodes that had properties modified.
        The changes to computed style properties are only tracked for nodes pushed to the front-end
        by the DOM agent. If no changes to the tracked properties occur after the node has been pushed
        to the front-end, no updates will be issued for the node.

        **EXPERIMENTAL**

        :param properties_to_track:
        '''
        params: T_JSON_DICT = dict()
        params['propertiesToTrack'] = [i.to_json() for i in properties_to_track]
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.trackComputedStyleUpdates',
            'params': params,
        }
        json = yield cmd_dict

    def take_computed_style_updates() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[dom.NodeId]]:
        '''
        Polls the next batch of computed style updates.

        **EXPERIMENTAL**

        :returns: The list of node Ids that have their tracked computed styles updated.
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.takeComputedStyleUpdates',
        }
        json = yield cmd_dict
        return [dom.NodeId.from_json(i) for i in json['nodeIds']]

    def set_effective_property_value_for_node(
            node_id: dom.NodeId,
            property_name: str,
            value: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Find a rule with the given active property for the given node and set the new value for this
        property

        :param node_id: The element id for which to set property.
        :param property_name:
        :param value:
        '''
        params: T_JSON_DICT = dict()
        params['nodeId'] = node_id.to_json()
        params['propertyName'] = property_name
        params['value'] = value
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setEffectivePropertyValueForNode',
            'params': params,
        }
        json = yield cmd_dict

    def set_property_rule_property_name(
            style_sheet_id: StyleSheetId,
            range_: SourceRange,
            property_name: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,Value]:
        '''
        Modifies the property rule property name.

        :param style_sheet_id:
        :param range_:
        :param property_name:
        :returns: The resulting key text after modification.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['range'] = range_.to_json()
        params['propertyName'] = property_name
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setPropertyRulePropertyName',
            'params': params,
        }
        json = yield cmd_dict
        return Value.from_json(json['propertyName'])

    def set_keyframe_key(
            style_sheet_id: StyleSheetId,
            range_: SourceRange,
            key_text: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,Value]:
        '''
        Modifies the keyframe rule key text.

        :param style_sheet_id:
        :param range_:
        :param key_text:
        :returns: The resulting key text after modification.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['range'] = range_.to_json()
        params['keyText'] = key_text
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setKeyframeKey',
            'params': params,
        }
        json = yield cmd_dict
        return Value.from_json(json['keyText'])

    def set_media_text(
            style_sheet_id: StyleSheetId,
            range_: SourceRange,
            text: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,CSSMedia]:
        '''
        Modifies the rule selector.

        :param style_sheet_id:
        :param range_:
        :param text:
        :returns: The resulting CSS media rule after modification.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['range'] = range_.to_json()
        params['text'] = text
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setMediaText',
            'params': params,
        }
        json = yield cmd_dict
        return CSSMedia.from_json(json['media'])

    def set_container_query_text(
            style_sheet_id: StyleSheetId,
            range_: SourceRange,
            text: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,CSSContainerQuery]:
        '''
        Modifies the expression of a container query.

        **EXPERIMENTAL**

        :param style_sheet_id:
        :param range_:
        :param text:
        :returns: The resulting CSS container query rule after modification.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['range'] = range_.to_json()
        params['text'] = text
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setContainerQueryText',
            'params': params,
        }
        json = yield cmd_dict
        return CSSContainerQuery.from_json(json['containerQuery'])

    def set_supports_text(
            style_sheet_id: StyleSheetId,
            range_: SourceRange,
            text: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,CSSSupports]:
        '''
        Modifies the expression of a supports at-rule.

        **EXPERIMENTAL**

        :param style_sheet_id:
        :param range_:
        :param text:
        :returns: The resulting CSS Supports rule after modification.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['range'] = range_.to_json()
        params['text'] = text
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setSupportsText',
            'params': params,
        }
        json = yield cmd_dict
        return CSSSupports.from_json(json['supports'])

    def set_scope_text(
            style_sheet_id: StyleSheetId,
            range_: SourceRange,
            text: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,CSSScope]:
        '''
        Modifies the expression of a scope at-rule.

        **EXPERIMENTAL**

        :param style_sheet_id:
        :param range_:
        :param text:
        :returns: The resulting CSS Scope rule after modification.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['range'] = range_.to_json()
        params['text'] = text
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setScopeText',
            'params': params,
        }
        json = yield cmd_dict
        return CSSScope.from_json(json['scope'])

    def set_rule_selector(
            style_sheet_id: StyleSheetId,
            range_: SourceRange,
            selector: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,SelectorList]:
        '''
        Modifies the rule selector.

        :param style_sheet_id:
        :param range_:
        :param selector:
        :returns: The resulting selector list after modification.
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['range'] = range_.to_json()
        params['selector'] = selector
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setRuleSelector',
            'params': params,
        }
        json = yield cmd_dict
        return SelectorList.from_json(json['selectorList'])

    def set_style_sheet_text(
            style_sheet_id: StyleSheetId,
            text: str
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Optional[str]]:
        '''
        Sets the new stylesheet text.

        :param style_sheet_id:
        :param text:
        :returns: *(Optional)* URL of source map associated with script (if any).
        '''
        params: T_JSON_DICT = dict()
        params['styleSheetId'] = style_sheet_id.to_json()
        params['text'] = text
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setStyleSheetText',
            'params': params,
        }
        json = yield cmd_dict
        return str(json['sourceMapURL']) if json.get('sourceMapURL', None) is not None else None

    def set_style_texts(
            edits: typing.List[StyleDeclarationEdit],
            node_for_property_syntax_validation: typing.Optional[dom.NodeId] = None
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[CSSStyle]]:
        '''
        Applies specified style edits one after another in the given order.

        :param edits:
        :param node_for_property_syntax_validation: **(EXPERIMENTAL)** *(Optional)* NodeId for the DOM node in whose context custom property declarations for registered properties should be validated. If omitted, declarations in the new rule text can only be validated statically, which may produce incorrect results if the declaration contains a var() for example.
        :returns: The resulting styles after modification.
        '''
        params: T_JSON_DICT = dict()
        params['edits'] = [i.to_json() for i in edits]
        if node_for_property_syntax_validation is not None:
            params['nodeForPropertySyntaxValidation'] = node_for_property_syntax_validation.to_json()
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setStyleTexts',
            'params': params,
        }
        json = yield cmd_dict
        return [CSSStyle.from_json(i) for i in json['styles']]

    def start_rule_usage_tracking() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Enables the selector recording.
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.startRuleUsageTracking',
        }
        json = yield cmd_dict

    def stop_rule_usage_tracking() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.List[RuleUsage]]:
        '''
        Stop tracking rule usage and return the list of rules that were used since last call to
        ``takeCoverageDelta`` (or since start of coverage instrumentation).

        :returns:
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.stopRuleUsageTracking',
        }
        json = yield cmd_dict
        return [RuleUsage.from_json(i) for i in json['ruleUsage']]

    def take_coverage_delta() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,typing.Tuple[typing.List[RuleUsage], float]]:
        '''
        Obtain list of rules that became used since last call to this method (or since start of coverage
        instrumentation).

        :returns: A tuple with the following items:

            0. **coverage** -
            1. **timestamp** - Monotonically increasing time, in seconds.
        '''
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.takeCoverageDelta',
        }
        json = yield cmd_dict
        return (
            [RuleUsage.from_json(i) for i in json['coverage']],
            float(json['timestamp'])
        )

    def set_local_fonts_enabled(
            enabled: bool
        ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
        '''
        Enables/disables rendering of local CSS fonts (enabled by default).

        **EXPERIMENTAL**

        :param enabled: Whether rendering of local fonts is enabled.
        '''
        params: T_JSON_DICT = dict()
        params['enabled'] = enabled
        cmd_dict: T_JSON_DICT = {
            'method': 'CSS.setLocalFontsEnabled',
            'params': params,
        }
        json = yield cmd_dict

    @event_class('CSS.fontsUpdated')
    @dataclass
    class FontsUpdated:
        '''
        Fires whenever a web font is updated.  A non-empty font parameter indicates a successfully loaded
        web font.
        '''
        #: The web font that has loaded.
        font: typing.Optional[FontFace]

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> FontsUpdated:
            return cls(
                font=FontFace.from_json(json['font']) if json.get('font', None) is not None else None
            )

    @event_class('CSS.mediaQueryResultChanged')
    @dataclass
    class MediaQueryResultChanged:
        '''
        Fires whenever a MediaQuery result changes (for example, after a browser window has been
        resized.) The current implementation considers only viewport-dependent media features.
        '''

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> MediaQueryResultChanged:
            return cls(

            )

    @event_class('CSS.styleSheetAdded')
    @dataclass
    class StyleSheetAdded:
        '''
        Fired whenever an active document stylesheet is added.
        '''
        #: Added stylesheet metainfo.
        header: CSSStyleSheetHeader

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> StyleSheetAdded:
            return cls(
                header=CSSStyleSheetHeader.from_json(json['header'])
            )

    @event_class('CSS.styleSheetChanged')
    @dataclass
    class StyleSheetChanged:
        '''
        Fired whenever a stylesheet is changed as a result of the client operation.
        '''
        style_sheet_id: StyleSheetId

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> StyleSheetChanged:
            return cls(
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId'])
            )

    @event_class('CSS.styleSheetRemoved')
    @dataclass
    class StyleSheetRemoved:
        '''
        Fired whenever an active document stylesheet is removed.
        '''
        #: Identifier of the removed stylesheet.
        style_sheet_id: StyleSheetId

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> StyleSheetRemoved:
            return cls(
                style_sheet_id=StyleSheetId.from_json(json['styleSheetId'])
            )

    @event_class('CSS.computedStyleUpdated')
    @dataclass
    class ComputedStyleUpdated:
        '''
        **EXPERIMENTAL**

        '''
        #: The node id that has updated computed styles.
        node_id: dom.NodeId

        @classmethod
        def from_json(cls, json: T_JSON_DICT) -> ComputedStyleUpdated:
            return cls(
                node_id=dom.NodeId.from_json(json['nodeId'])
            )