CSS Inspector

 
General

The user interface should work as follow:
 
The user selects a node in the DOM inspector. The CSS view has 5 categories for that node:
 
- computed style
 
- inline style
 
- direct matching rules
 
- inherited rules
 
- default rules
 
Each of the category can be unfolded, at the top is a search field, which will apply to all categories so that it's easy to understand how a certain node exactly gets his style.
 
 
Terminology

A matching rule does include all "states" of a node, like hover, active, visited.
 
 
Client side / host side

The protocol does provide all information so that no eval command must be used to get the data.
Analysing and marking the overwritten rules will be done on the client side, but all info to do so will be provided by the protocol.
This gives the possibility that the user interface can fake "states" like hover, active, visited and display the rules accordingly.
 
 
CSS Protocol extensions


;       
; Property List
;       

COMMAND ::= "<css-get-index-map>"
              TAG
              [ FORMAT ]
            "</css-get-index-map>"
 
EVENT ::= "<css-get-index-map-reply>"
              TAG
              INDEX-MAP
          "</css-get-index-map-reply>"
 
 
; this is the list with all css properties
; the index in the list will be used a shortcut for the property name
; by the other commands
; e.g ["background", "background-attachment", "background-color", ... ]
;
; Note: this list is only valid for one Opera instance, don't cache the results

; Decides the wanted format in EVENT
; if you are fetching the data from javascript code you might want to
; use the "json" format since it is immediately parsed by the javascript
; interpreter, for other tools XML is probably preferred.
;
; If unspecified it defaults to "xml"
FORMAT ::= "xml" | "json"
 
INDEX-MAP ::= "["  PROPERTY-NAME { "," PROPERTY-NAME } "]"
 
PROPERTY-NAME ::= <json encoded property name>


;            
; Genearl stylesheet data
;            


; to get the general data for all stylesheets from a document
; corresponses to the document.styleSheets collection

COMMAND ::= "<css-get-all-stylesheets>"
              TAG
              RUNTIME-ID
              [ FORMAT ]
            "</css-get-all-stylesheets>"

EVENT :: = "<css-get-all-stylesheets-reply>"
             TAG
             STYLESHEETS
           "</css-get-sall-stylesheets-reply>"

; the order in the list does correspond to the index in document.styleSheets

STYLESHEETS ::= "[" STYLESHEET { "," STYLESHEET } "]"

STYLESHEET ::=  "["
                  OBJECT-ID ","
                  DISABLED "," 
                  HREF "," 
                  MEDIA-LIST "," 
                  OWNERNODE "," 
                  OWNERRULE "," 
                  PARENT-STYLESHEET ","
                  TITLE ","
                  TYPE
                "]"

; http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet

DISABLED ::= FLAG
HREF ::= <json encoded href>
MEDIA-LIST ::= "[" MEDIA { "," MEDIA } "]"
OWNERNODE ::= <object-id> | "null"
OWNERRULE ::= <object-id> | "null"
PARENT-STYLESHEET ::= <object-id> | "null"
TITLE ::= STRING
TYPE ::= STRING

MEDIA ::= STRING


;           
; get a live stylesheet
;           


; to retrieve a whole live stylesheet and its CSS rules
;
; to fetch CSS rules for any given HTML use the command <css-get-style-declarations>
;
; Note: The stylesheet IDs don't exist until they have been created with <css-get-all-stylesheets>

COMMAND ::= "<css-get-stylesheet>"
              TAG
              RUNTIME-ID
              "<stylesheet-id>"  STYLESHEET-ID  "</stylesheet-id>"
              [ FORMAT ]
            "</css-get-stylesheet>"

EVENT :: = "<css-get-stylesheet-reply>"
             TAG
             RULE-LIST
           "</css-get-stylesheet-reply>"


; corresponses to cssRules
RULE-LIST ::= "[" RULE { "," RULE } ]


; http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule

RULE ::=    UNKNOWN-RULE
          | STYLE-RULE-MULTIPLE
          | CHARSET-RULE
          | IMPORT-RULE
          | MEDIA-RULE
          | FONT-FACE-RULE
          | PAGE-RULE

; http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule

STYLE-RULE-MULTIPLE ::= "["
                         "[" STYLE-RULE-HEADER-MULTIPLE "],"
                         "[" INDEX-LIST "],"
                         "[" VALUE-LIST "],"
                         "[" PRIORITY-LIST "]"
                        "]"

STYLE-RULE-HEADER-MULTIPLE ::= STYLESHEET-ID "," RULE-ID "," RULE-TYPE "," SELECTOR-LIST "," SPECIFICITY-LIST

SELECTOR-LIST ::= "[" SELECTOR-TEXT { "," SELECTOR-TEXT } "]"
SPECIFICITY-LIST ::= "[" SPECIFICITY { "," SPECIFICITY } "]"
 
STYLESHEET-ID ::= <object id for the stylesheet>
RULE-ID ::= <object id for the rule>
RULE-TYPE ::= UNSIGNED

; RULE-TYPE values:
; 0 - UNKNOWN
; 1 - STYLE
; 2 - CHARSET
; 3 - IMPORT
; 4 - MEDIA
; 5 - FONT_FACE
; 6 - PAGE
; 7 - NAMESPACE // Not supported

SPECIFICITY ::= UNSIGNED
SELECTOR-TEXT ::= <json escaped selector text>

; http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule
MEDIA-RULE ::= "[[" MEDIA-RULE-HEADER "],[" RULE-LIST "]]"

MEDIA-RULE-HEADER ::= STYLESHEET-ID "," RULE-ID "," RULE-TYPE "," MEDIA-LIST

; http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule
; the first stylesheet id is the owner of this rule, 
; the second the id for the imported stylesheet

IMPORT-RULE ::= "[[" STYLESHEET-ID "," RULE-ID "," RULE-TYPE "," HREF "," MEDIA-LIST "," STYLESHEET-ID "]]"

; i'm not sure if CHARSET-RULE, FONT-FACE-RULE and PAGE-RULE 
; are supported in Opera, i think atleast FONT-FACE-RULE is.
; for details see http://www.w3.org/TR/DOM-Level-2-Style/css.html

CHARSET-RULE ::= "[[" STYLESHEET-ID "," RULE-ID "," RULE-TYPE "," CHARSET "]]"
CHARSET ::= <json escaped charset text>

FONT_FACE-RULE ::= "["
                     "[" FONT_FACE-RULE-HEADER "]"
                     "[" INDEX-LIST "]"
                     "[" VALUE-LIST "]"
                     "[" PRIORITY-LIST "]"
                   "]"
FONT_FACE-RULE-HEADER ::= STYLESHEET-ID "," RULE-ID "," RULE-TYPE

PAGE-RULE ::= "["
                "[" PAGE-RULE-HEADER "]"
                "[" INDEX-LIST "]"
                "[" VALUE-LIST "]"
                "[" PRIORITY-LIST "]"
              "]"
PAGE-RULE ::= STYLESHEET-ID "," RULE-ID "," RULE-TYPE "," SPECIFICITY "," PAGE-SELECTOR "," PSEUDO-CLASS
PAGE-SELECTOR ::= <json escaped selector text> | "null"
PSEUDO-CLASS ::= UNSIGNED


 
;                        
; get the matching style rules for a given element
;                        
 
; command to get all matching style declarations for a given element
 
COMMAND ::= "<css-get-style-declarations>"
              TAG
              RUNTIME-ID
              OBJECT-ID
              [ FORMAT ]
            "</css-get-style-declarations>"
 
 
FLAG ::= "0" | "1"
 
EVENT :: = "<css-get-style-declarations-reply>"
             TAG
             MATCHING-STYLE-DECLARATIONS
           "</css-get-style-declarations-reply>"
 
MATCHING-STYLE-DECLARATIONS ::= "["
                                COMPUTED-STYLE ","
                                NODE-CHAIN-STYLE-CASCADE
                                "]"

; this is sorted according to the index map
; e.g the first value would be the complete background rule,
; the second the background-attachement and so one
COMPUTED-STYLE ::= "[" PROPERTY-VALUE { "," PROPERTY-VALUE } "]"

; the target node first, any following cascade without non-inheritable rules.
NODE-CHAIN-STYLE-CASCADE ::= "[" NODE-STYLE-CASCADE { "," NODE-STYLE-CASCADE  } "]"
NODE-STYLE-CASCADE       ::= "[[" NODE-HEADER "],"
                               STYLE-DECLARATION-LIST
                             "]"
NODE-HEADER              ::= OBJECT-ID "," ELEMENT-NAME
STYLE-DECLARATION-LIST   ::= "[" STYLE-DECLARATION { "," STYLE-DECLARATION } "]"
STYLE-DECLARATION        ::= ELEMENT-RULE | AUTHOR-RULE | LOCAL-RULE | USER-AGENT-RULE

; Common header for style declarations
RULE-HEADER    ::= RULE-ORIGIN
RULE-ORIGIN    ::=   "1" ; user-agent (ie. default)
                   | "2" ; local (ie. user)
                   | "3" ; author (ie. stylesheet)
                   | "4" ; element (ie. in-line)
                   
; Common property list for style declarations
PROPERTIES ::= "[" INDEX-LIST "],"
               "[" VALUE-LIST "],"
               "[" PRIORITY-LIST "],"
               "[" STATUS-LIST "]"

ELEMENT-RULE      ::= "[[" ELEMENT-HEADER "]," PROPERTIES "]"
ELEMENT-HEADER    ::= RULE-HEADER ; object-id and element-name is part of NODE-HEADER

AUTHOR-RULE       ::= "[[" AUTHOR-HEADER "]," PROPERTIES "]"
AUTHOR-HEADER     ::= RULE-HEADER "," STYLESHEET-ID "," RULE-ID "," RULE-TYPE "," SPECIFICITY "," SELECTOR-TEXT

USER-AGENT-RULE   ::= "[[" USER-AGENT-HEADER "]," PROPERTIES "]"
USER-AGENT-HEADER ::= RULE-HEADER ; object-id and element-name is part of NODE-HEADER

LOCAL-RULE       ::= "[[" LOCAL-HEADER "]," PROPERTIES "]"
LOCAL-HEADER     ::= RULE-HEADER "," SPECIFICITY "," SELECTOR-TEXT

; indexes according to the index map for the set properties on this style declaration
INDEX-LIST ::= UNSIGNED { "," UNSIGNED }
 
; the according values
VALUE-LIST ::= PROPERTY-VALUE { "," PROPERTY-VALUE }
 
; the according priority flag
PRIORITY-LIST ::= PRIORITY { "," PRIORITY }
PRIORITY      ::= "0" | "1"

STATUS-LIST     ::= PROPERTY-STATUS { "," PROPERTY-STATUS }
PROPERTY-STATUS ::=   "0" ; overwritten, overwritten by other rule
                    | "1" ; standard, in use
 
PROPERTY-VALUE ::= <json encoded css property value>
