Home | History | Annotate | Download | only in front_end
      1 /*
      2  * Copyright (C) 2010 Nikita Vasilyev. All rights reserved.
      3  * Copyright (C) 2010 Joseph Pecoraro. All rights reserved.
      4  * Copyright (C) 2010 Google Inc. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions are
      8  * met:
      9  *
     10  *     * Redistributions of source code must retain the above copyright
     11  * notice, this list of conditions and the following disclaimer.
     12  *     * Redistributions in binary form must reproduce the above
     13  * copyright notice, this list of conditions and the following disclaimer
     14  * in the documentation and/or other materials provided with the
     15  * distribution.
     16  *     * Neither the name of Google Inc. nor the names of its
     17  * contributors may be used to endorse or promote products derived from
     18  * this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /**
     34  * @constructor
     35  * @param {!Array.<!CSSAgent.CSSPropertyInfo|string>} properties
     36  */
     37 WebInspector.CSSMetadata = function(properties)
     38 {
     39     this._values = /** !Array.<string> */ ([]);
     40     this._longhands = {};
     41     this._shorthands = {};
     42     for (var i = 0; i < properties.length; ++i) {
     43         var property = properties[i];
     44         if (typeof property === "string") {
     45             this._values.push(property);
     46             continue;
     47         }
     48 
     49         var propertyName = property.name;
     50         this._values.push(propertyName);
     51 
     52         var longhands = properties[i].longhands;
     53         if (longhands) {
     54             this._longhands[propertyName] = longhands;
     55             for (var j = 0; j < longhands.length; ++j) {
     56                 var longhandName = longhands[j];
     57                 var shorthands = this._shorthands[longhandName];
     58                 if (!shorthands) {
     59                     shorthands = [];
     60                     this._shorthands[longhandName] = shorthands;
     61                 }
     62                 shorthands.push(propertyName);
     63             }
     64         }
     65     }
     66     this._values.sort();
     67 }
     68 
     69 /**
     70  * @type {!WebInspector.CSSMetadata}
     71  */
     72 WebInspector.CSSMetadata.cssPropertiesMetainfo = new WebInspector.CSSMetadata([]);
     73 
     74 WebInspector.CSSMetadata.isColorAwareProperty = function(propertyName)
     75 {
     76     return WebInspector.CSSMetadata._colorAwareProperties[propertyName] === true;
     77 }
     78 
     79 WebInspector.CSSMetadata.colors = function()
     80 {
     81     if (!WebInspector.CSSMetadata._colorsKeySet)
     82         WebInspector.CSSMetadata._colorsKeySet = WebInspector.CSSMetadata._colors.keySet();
     83     return WebInspector.CSSMetadata._colorsKeySet;
     84 }
     85 
     86 // Taken from http://www.w3.org/TR/CSS21/propidx.html.
     87 WebInspector.CSSMetadata.InheritedProperties = [
     88     "azimuth", "border-collapse", "border-spacing", "caption-side", "color", "cursor", "direction", "elevation",
     89     "empty-cells", "font-family", "font-size", "font-style", "font-variant", "font-weight", "font", "letter-spacing",
     90     "line-height", "list-style-image", "list-style-position", "list-style-type", "list-style", "orphans", "pitch-range",
     91     "pitch", "quotes", "resize", "richness", "speak-header", "speak-numeral", "speak-punctuation", "speak", "speech-rate", "stress",
     92     "text-align", "text-indent", "text-transform", "text-shadow", "visibility", "voice-family", "volume", "white-space", "widows",
     93     "word-spacing", "zoom"
     94 ].keySet();
     95 
     96 // These non-standard Blink-specific properties augment the InheritedProperties.
     97 WebInspector.CSSMetadata.NonStandardInheritedProperties = [
     98     "-webkit-font-smoothing"
     99 ].keySet();
    100 
    101 /**
    102  * @param {string} name
    103  * @return {string}
    104  */
    105 WebInspector.CSSMetadata.canonicalPropertyName = function(name)
    106 {
    107     if (!name || name.length < 9 || name.charAt(0) !== "-")
    108         return name.toLowerCase();
    109     var match = name.match(/(?:-webkit-)(.+)/);
    110     if (!match)
    111         return name.toLowerCase();
    112     return match[1].toLowerCase();
    113 }
    114 
    115 /**
    116  * @param {string} propertyName
    117  * @return {boolean}
    118  */
    119 WebInspector.CSSMetadata.isPropertyInherited = function(propertyName)
    120 {
    121     return !!(WebInspector.CSSMetadata.InheritedProperties[WebInspector.CSSMetadata.canonicalPropertyName(propertyName)]
    122             || WebInspector.CSSMetadata.NonStandardInheritedProperties[propertyName.toLowerCase()]);
    123 }
    124 
    125 WebInspector.CSSMetadata._colors = [
    126     "aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "orange", "purple", "red",
    127     "silver", "teal", "white", "yellow", "transparent", "currentcolor", "grey", "aliceblue", "antiquewhite",
    128     "aquamarine", "azure", "beige", "bisque", "blanchedalmond", "blueviolet", "brown", "burlywood", "cadetblue",
    129     "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
    130     "darkgoldenrod", "darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange",
    131     "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkslategrey",
    132     "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick",
    133     "floralwhite", "forestgreen", "gainsboro", "ghostwhite", "gold", "goldenrod", "greenyellow", "honeydew", "hotpink",
    134     "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue",
    135     "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink",
    136     "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", "lightsteelblue", "lightyellow",
    137     "limegreen", "linen", "magenta", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
    138     "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream",
    139     "mistyrose", "moccasin", "navajowhite", "oldlace", "olivedrab", "orangered", "orchid", "palegoldenrod", "palegreen",
    140     "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "rosybrown",
    141     "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "skyblue", "slateblue",
    142     "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan", "thistle", "tomato", "turquoise", "violet",
    143     "wheat", "whitesmoke", "yellowgreen"
    144 ];
    145 
    146 WebInspector.CSSMetadata._colorAwareProperties = [
    147     "background", "background-color", "background-image", "border", "border-color", "border-top", "border-right", "border-bottom",
    148     "border-left", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "box-shadow", "color",
    149     "fill", "outline", "outline-color", "stroke", "text-line-through-color", "text-overline-color",
    150     "text-shadow", "text-underline-color", "-webkit-box-shadow", "-webkit-column-rule-color",
    151     "-webkit-text-decoration-color", "-webkit-text-emphasis", "-webkit-text-emphasis-color"
    152 ].keySet();
    153 
    154 WebInspector.CSSMetadata._propertyDataMap = {
    155     "table-layout": { values: [
    156         "auto", "fixed"
    157     ] },
    158     "visibility": { values: [
    159         "hidden", "visible", "collapse"
    160     ] },
    161     "background-repeat": { values: [
    162         "repeat", "repeat-x", "repeat-y", "no-repeat", "space", "round"
    163     ] },
    164     "content": { values: [
    165         "list-item", "close-quote", "no-close-quote", "no-open-quote", "open-quote"
    166     ] },
    167     "list-style-image": { values: [
    168         "none"
    169     ] },
    170     "clear": { values: [
    171         "none", "left", "right", "both"
    172     ] },
    173     "text-underline-mode": { values: [
    174         "continuous", "skip-white-space"
    175     ] },
    176     "overflow-x": { values: [
    177         "hidden", "auto", "visible", "overlay", "scroll"
    178     ] },
    179     "stroke-linejoin": { values: [
    180         "round", "miter", "bevel"
    181     ] },
    182     "baseline-shift": { values: [
    183         "baseline", "sub", "super"
    184     ] },
    185     "border-bottom-width": { values: [
    186         "medium", "thick", "thin"
    187     ] },
    188     "marquee-speed": { values: [
    189         "normal", "slow", "fast"
    190     ] },
    191     "margin-top-collapse": { values: [
    192         "collapse", "separate", "discard"
    193     ] },
    194     "max-height": { values: [
    195         "none"
    196     ] },
    197     "box-orient": { values: [
    198         "horizontal", "vertical", "inline-axis", "block-axis"
    199     ], },
    200     "font-stretch": { values: [
    201         "normal", "wider", "narrower", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed",
    202         "semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
    203     ] },
    204     "text-underline-style": { values: [
    205         "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
    206     ] },
    207     "text-overline-mode": { values: [
    208         "continuous", "skip-white-space"
    209     ] },
    210     "-webkit-background-composite": { values: [
    211         "highlight", "clear", "copy", "source-over", "source-in", "source-out", "source-atop", "destination-over",
    212         "destination-in", "destination-out", "destination-atop", "xor", "plus-darker", "plus-lighter"
    213     ] },
    214     "border-left-width": { values: [
    215         "medium", "thick", "thin"
    216     ] },
    217     "-webkit-writing-mode": { values: [
    218         "lr", "rl", "tb", "lr-tb", "rl-tb", "tb-rl", "horizontal-tb", "vertical-rl", "vertical-lr", "horizontal-bt"
    219     ] },
    220     "text-line-through-mode": { values: [
    221         "continuous", "skip-white-space"
    222     ] },
    223     "border-collapse": { values: [
    224         "collapse", "separate"
    225     ] },
    226     "page-break-inside": { values: [
    227         "auto", "avoid"
    228     ] },
    229     "border-top-width": { values: [
    230         "medium", "thick", "thin"
    231     ] },
    232     "outline-color": { values: [
    233         "invert"
    234     ] },
    235     "text-line-through-style": { values: [
    236         "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
    237     ] },
    238     "outline-style": { values: [
    239         "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
    240     ] },
    241     "cursor": { values: [
    242         "none", "copy", "auto", "crosshair", "default", "pointer", "move", "vertical-text", "cell", "context-menu",
    243         "alias", "progress", "no-drop", "not-allowed", "-webkit-zoom-in", "-webkit-zoom-out", "e-resize", "ne-resize",
    244         "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "ew-resize", "ns-resize",
    245         "nesw-resize", "nwse-resize", "col-resize", "row-resize", "text", "wait", "help", "all-scroll", "-webkit-grab",
    246         "-webkit-grabbing"
    247     ] },
    248     "border-width": { values: [
    249         "medium", "thick", "thin"
    250     ] },
    251     "size": { values: [
    252         "a3", "a4", "a5", "b4", "b5", "landscape", "ledger", "legal", "letter", "portrait"
    253     ] },
    254     "background-size": { values: [
    255         "contain", "cover"
    256     ] },
    257     "direction": { values: [
    258         "ltr", "rtl"
    259     ] },
    260     "marquee-direction": { values: [
    261         "left", "right", "auto", "reverse", "forwards", "backwards", "ahead", "up", "down"
    262     ] },
    263     "enable-background": { values: [
    264         "accumulate", "new"
    265     ] },
    266     "float": { values: [
    267         "none", "left", "right"
    268     ] },
    269     "overflow-y": { values: [
    270         "hidden", "auto", "visible", "overlay", "scroll"
    271     ] },
    272     "margin-bottom-collapse": { values: [
    273         "collapse",  "separate", "discard"
    274     ] },
    275     "box-reflect": { values: [
    276         "left", "right", "above", "below"
    277     ] },
    278     "overflow": { values: [
    279         "hidden", "auto", "visible", "overlay", "scroll"
    280     ] },
    281     "text-rendering": { values: [
    282         "auto", "optimizeSpeed", "optimizeLegibility", "geometricPrecision"
    283     ] },
    284     "text-align": { values: [
    285         "-webkit-auto", "start", "end", "left", "right", "center", "justify", "-webkit-left", "-webkit-right", "-webkit-center"
    286     ] },
    287     "list-style-position": { values: [
    288         "outside", "inside", "hanging"
    289     ] },
    290     "margin-bottom": { values: [
    291         "auto"
    292     ] },
    293     "color-interpolation": { values: [
    294         "linearrgb"
    295     ] },
    296     "background-origin": { values: [
    297         "border-box", "content-box", "padding-box"
    298     ] },
    299     "word-wrap": { values: [
    300         "normal", "break-word"
    301     ] },
    302     "font-weight": { values: [
    303         "normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900"
    304     ] },
    305     "margin-before-collapse": { values: [
    306         "collapse", "separate", "discard"
    307     ] },
    308     "text-overline-width": { values: [
    309         "normal", "medium", "auto", "thick", "thin"
    310     ] },
    311     "text-transform": { values: [
    312         "none", "capitalize", "uppercase", "lowercase"
    313     ] },
    314     "border-right-style": { values: [
    315         "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
    316     ] },
    317     "border-left-style": { values: [
    318         "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
    319     ] },
    320     "-webkit-text-emphasis": { values: [
    321         "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame"
    322     ] },
    323     "font-style": { values: [
    324         "italic", "oblique", "normal"
    325     ] },
    326     "speak": { values: [
    327         "none", "normal", "spell-out", "digits", "literal-punctuation", "no-punctuation"
    328     ] },
    329     "color-rendering": { values: [
    330         "auto", "optimizeSpeed", "optimizeQuality"
    331     ] },
    332     "list-style-type": { values: [
    333         "none", "inline", "disc", "circle", "square", "decimal", "decimal-leading-zero", "arabic-indic", "binary", "bengali",
    334         "cambodian", "khmer", "devanagari", "gujarati", "gurmukhi", "kannada", "lower-hexadecimal", "lao", "malayalam",
    335         "mongolian", "myanmar", "octal", "oriya", "persian", "urdu", "telugu", "tibetan", "thai", "upper-hexadecimal",
    336         "lower-roman", "upper-roman", "lower-greek", "lower-alpha", "lower-latin", "upper-alpha", "upper-latin", "afar",
    337         "ethiopic-halehame-aa-et", "ethiopic-halehame-aa-er", "amharic", "ethiopic-halehame-am-et", "amharic-abegede",
    338         "ethiopic-abegede-am-et", "cjk-earthly-branch", "cjk-heavenly-stem", "ethiopic", "ethiopic-halehame-gez",
    339         "ethiopic-abegede", "ethiopic-abegede-gez", "hangul-consonant", "hangul", "lower-norwegian", "oromo",
    340         "ethiopic-halehame-om-et", "sidama", "ethiopic-halehame-sid-et", "somali", "ethiopic-halehame-so-et", "tigre",
    341         "ethiopic-halehame-tig", "tigrinya-er", "ethiopic-halehame-ti-er", "tigrinya-er-abegede",
    342         "ethiopic-abegede-ti-er", "tigrinya-et", "ethiopic-halehame-ti-et", "tigrinya-et-abegede",
    343         "ethiopic-abegede-ti-et", "upper-greek", "upper-norwegian", "asterisks", "footnotes", "hebrew", "armenian",
    344         "lower-armenian", "upper-armenian", "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha",
    345         "katakana-iroha"
    346     ] },
    347     "-webkit-text-combine": { values: [
    348         "none", "horizontal"
    349     ] },
    350     "outline": { values: [
    351         "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
    352     ] },
    353     "font": { values: [
    354         "caption", "icon", "menu", "message-box", "small-caption", "-webkit-mini-control", "-webkit-small-control",
    355         "-webkit-control", "status-bar", "italic", "oblique", "small-caps", "normal", "bold", "bolder", "lighter",
    356         "100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium",
    357         "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller", "larger", "serif", "sans-serif", "cursive",
    358         "fantasy", "monospace", "-webkit-body", "-webkit-pictograph"
    359     ] },
    360     "dominant-baseline": { values: [
    361         "middle", "auto", "central", "text-before-edge", "text-after-edge", "ideographic", "alphabetic", "hanging",
    362         "mathematical", "use-script", "no-change", "reset-size"
    363     ] },
    364     "display": { values: [
    365         "none", "inline", "block", "list-item", "run-in", "compact", "inline-block", "table", "inline-table",
    366         "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group",
    367         "table-column", "table-cell", "table-caption", "-webkit-box", "-webkit-inline-box",
    368         "flex", "inline-flex", "grid", "inline-grid"
    369     ] },
    370     "-webkit-text-emphasis-position": { values: [
    371         "over", "under"
    372     ] },
    373     "image-rendering": { values: [
    374         "auto", "optimizeSpeed", "optimizeQuality"
    375     ] },
    376     "alignment-baseline": { values: [
    377         "baseline", "middle", "auto", "before-edge", "after-edge", "central", "text-before-edge", "text-after-edge",
    378         "ideographic", "alphabetic", "hanging", "mathematical"
    379     ] },
    380     "outline-width": { values: [
    381         "medium", "thick", "thin"
    382     ] },
    383     "text-line-through-width": { values: [
    384         "normal", "medium", "auto", "thick", "thin"
    385     ] },
    386     "box-align": { values: [
    387         "baseline", "center", "stretch", "start", "end"
    388     ] },
    389     "border-right-width": { values: [
    390         "medium", "thick", "thin"
    391     ] },
    392     "border-top-style": { values: [
    393         "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
    394     ] },
    395     "line-height": { values: [
    396         "normal"
    397     ] },
    398     "text-overflow": { values: [
    399         "clip", "ellipsis"
    400     ] },
    401     "overflow-wrap": { values: [
    402         "normal", "break-word"
    403     ] },
    404     "box-direction": { values: [
    405         "normal", "reverse"
    406     ] },
    407     "margin-after-collapse": { values: [
    408         "collapse", "separate", "discard"
    409     ] },
    410     "page-break-before": { values: [
    411         "left", "right", "auto", "always", "avoid"
    412     ] },
    413     "border-image": { values: [
    414         "repeat", "stretch"
    415     ] },
    416     "text-decoration": { values: [
    417         "blink", "line-through", "overline", "underline"
    418     ] },
    419     "position": { values: [
    420         "absolute", "fixed", "relative", "static"
    421     ] },
    422     "font-family": { values: [
    423         "serif", "sans-serif", "cursive", "fantasy", "monospace", "-webkit-body", "-webkit-pictograph"
    424     ] },
    425     "text-overflow-mode": { values: [
    426         "clip", "ellipsis"
    427     ] },
    428     "border-bottom-style": { values: [
    429         "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
    430     ] },
    431     "unicode-bidi": { values: [
    432         "normal", "bidi-override", "embed"
    433     ] },
    434     "clip-rule": { values: [
    435         "nonzero", "evenodd"
    436     ] },
    437     "margin-left": { values: [
    438         "auto"
    439     ] },
    440     "margin-top": { values: [
    441         "auto"
    442     ] },
    443     "zoom": { values: [
    444         "normal", "document", "reset"
    445     ] },
    446     "text-overline-style": { values: [
    447         "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
    448     ] },
    449     "max-width": { values: [
    450         "none"
    451     ] },
    452     "caption-side": { values: [
    453         "top", "bottom"
    454     ] },
    455     "empty-cells": { values: [
    456         "hide", "show"
    457     ] },
    458     "pointer-events": { values: [
    459         "none", "all", "auto", "visible", "visiblepainted", "visiblefill", "visiblestroke", "painted", "fill", "stroke", "bounding-box"
    460     ] },
    461     "letter-spacing": { values: [
    462         "normal"
    463     ] },
    464     "background-clip": { values: [
    465         "border-box", "content-box", "padding-box"
    466     ] },
    467     "-webkit-font-smoothing": { values: [
    468         "none", "auto", "antialiased", "subpixel-antialiased"
    469     ] },
    470     "border": { values: [
    471         "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
    472     ] },
    473     "font-size": { values: [
    474         "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller",
    475         "larger"
    476     ] },
    477     "font-variant": { values: [
    478         "small-caps", "normal"
    479     ] },
    480     "vertical-align": { values: [
    481         "baseline", "middle", "sub", "super", "text-top", "text-bottom", "top", "bottom", "-webkit-baseline-middle"
    482     ] },
    483     "marquee-style": { values: [
    484         "none", "scroll", "slide", "alternate"
    485     ] },
    486     "white-space": { values: [
    487         "normal", "nowrap", "pre", "pre-line", "pre-wrap"
    488     ] },
    489     "text-underline-width": { values: [
    490         "normal", "medium", "auto", "thick", "thin"
    491     ] },
    492     "box-lines": { values: [
    493         "single", "multiple"
    494     ] },
    495     "page-break-after": { values: [
    496         "left", "right", "auto", "always", "avoid"
    497     ] },
    498     "clip-path": { values: [
    499         "none"
    500     ] },
    501     "margin": { values: [
    502         "auto"
    503     ] },
    504     "marquee-repetition": { values: [
    505         "infinite"
    506     ] },
    507     "margin-right": { values: [
    508         "auto"
    509     ] },
    510     "word-break": { values: [
    511         "normal", "break-all", "break-word"
    512     ] },
    513     "word-spacing": { values: [
    514         "normal"
    515     ] },
    516     "-webkit-text-emphasis-style": { values: [
    517         "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame"
    518     ] },
    519     "-webkit-transform": { values: [
    520         "scale", "scaleX", "scaleY", "scale3d", "rotate", "rotateX", "rotateY", "rotateZ", "rotate3d", "skew", "skewX", "skewY",
    521         "translate", "translateX", "translateY", "translateZ", "translate3d", "matrix", "matrix3d", "perspective"
    522     ] },
    523     "image-resolution": { values: [
    524         "from-image", "snap"
    525     ] },
    526     "box-sizing": { values: [
    527         "content-box", "padding-box", "border-box"
    528     ] },
    529     "clip": { values: [
    530         "auto"
    531     ] },
    532     "resize": { values: [
    533         "none", "both", "horizontal", "vertical"
    534     ] },
    535     "align-content": { values: [
    536         "flex-start", "flex-end", "center", "space-between", "space-around", "stretch"
    537     ] },
    538     "align-items": {  values: [
    539         "flex-start", "flex-end", "center", "baseline", "stretch"
    540     ] },
    541     "align-self": {  values: [
    542         "auto", "flex-start", "flex-end", "center", "baseline", "stretch"
    543     ] },
    544     "flex-direction": { values: [
    545         "row", "row-reverse", "column", "column-reverse"
    546     ] },
    547     "justify-content": { values: [
    548         "flex-start", "flex-end", "center", "space-between", "space-around"
    549     ] },
    550     "flex-wrap": { values: [
    551         "nowrap", "wrap", "wrap-reverse"
    552     ] },
    553     "-webkit-animation-timing-function": { values: [
    554         "ease", "linear", "ease-in", "ease-out", "ease-in-out", "step-start", "step-end", "steps", "cubic-bezier"
    555     ] },
    556     "-webkit-animation-direction": { values: [
    557         "normal", "reverse", "alternate", "alternate-reverse"
    558     ] },
    559     "-webkit-animation-play-state": { values: [
    560         "running", "paused"
    561     ] },
    562     "-webkit-animation-fill-mode": { values: [
    563         "none", "forwards", "backwards", "both"
    564     ] },
    565     "-webkit-backface-visibility": { values: [
    566         "visible", "hidden"
    567     ] },
    568     "-webkit-box-decoration-break": { values: [
    569         "slice", "clone"
    570     ] },
    571     "-webkit-column-break-after": { values: [
    572         "auto", "always", "avoid", "left", "right", "page", "column", "avoid-page", "avoid-column"
    573     ] },
    574     "-webkit-column-break-before": { values: [
    575         "auto", "always", "avoid", "left", "right", "page", "column", "avoid-page", "avoid-column"
    576     ] },
    577     "-webkit-column-break-inside": { values: [
    578         "auto", "avoid", "avoid-page", "avoid-column"
    579     ] },
    580     "-webkit-column-span": { values: [
    581         "none", "all"
    582     ] },
    583     "-webkit-column-count": { values: [
    584         "auto"
    585     ] },
    586     "-webkit-column-gap": { values: [
    587         "normal"
    588     ] },
    589     "-webkit-line-break": { values: [
    590         "auto", "loose", "normal", "strict"
    591     ] },
    592     "-webkit-perspective": { values: [
    593         "none"
    594     ] },
    595     "-webkit-perspective-origin": { values: [
    596         "left", "center", "right", "top", "bottom"
    597     ] },
    598     "text-align-last": { values: [
    599         "auto", "start", "end", "left", "right", "center", "justify"
    600     ] },
    601     "-webkit-text-decoration-line": { values: [
    602         "none", "underline", "overline", "line-through", "blink"
    603     ] },
    604     "-webkit-text-decoration-style": { values: [
    605         "solid", "double", "dotted", "dashed", "wavy"
    606     ] },
    607     "-webkit-text-decoration-skip": { values: [
    608         "none", "objects", "spaces", "ink", "edges", "box-decoration"
    609     ] },
    610     "-webkit-transform-origin": { values: [
    611         "left", "center", "right", "top", "bottom"
    612     ] },
    613     "-webkit-transform-style": { values: [
    614         "flat", "preserve-3d"
    615     ] },
    616     "-webkit-transition-timing-function": { values: [
    617         "ease", "linear", "ease-in", "ease-out", "ease-in-out", "step-start", "step-end", "steps", "cubic-bezier"
    618     ] },
    619 
    620     "-webkit-flex": { m: "flexbox" },
    621     "-webkit-flex-basis": { m: "flexbox" },
    622     "-webkit-flex-flow": { m: "flexbox" },
    623     "-webkit-flex-grow": { m: "flexbox" },
    624     "-webkit-flex-shrink": { m: "flexbox" },
    625     "-webkit-animation": { m: "animations" },
    626     "-webkit-animation-delay": { m: "animations" },
    627     "-webkit-animation-duration": { m: "animations" },
    628     "-webkit-animation-iteration-count": { m: "animations" },
    629     "-webkit-animation-name": { m: "animations" },
    630     "-webkit-column-rule": { m: "multicol" },
    631     "-webkit-column-rule-color": { m: "multicol", a: "crc" },
    632     "-webkit-column-rule-style": { m: "multicol", a: "crs" },
    633     "-webkit-column-rule-width": { m: "multicol", a: "crw" },
    634     "-webkit-column-width": { m: "multicol", a: "cw" },
    635     "-webkit-columns": { m: "multicol" },
    636     "-webkit-order": { m: "flexbox" },
    637     "-webkit-text-decoration-color": { m: "text-decor" },
    638     "-webkit-text-emphasis-color": { m: "text-decor" },
    639     "-webkit-transition": { m: "transitions" },
    640     "-webkit-transition-delay": { m: "transitions" },
    641     "-webkit-transition-duration": { m: "transitions" },
    642     "-webkit-transition-property": { m: "transitions" },
    643     "background": { m: "background" },
    644     "background-attachment": { m: "background" },
    645     "background-color": { m: "background" },
    646     "background-image": { m: "background" },
    647     "background-position": { m: "background" },
    648     "background-position-x": { m: "background" },
    649     "background-position-y": { m: "background" },
    650     "background-repeat-x": { m: "background" },
    651     "background-repeat-y": { m: "background" },
    652     "border-top": { m: "background" },
    653     "border-right": { m: "background" },
    654     "border-bottom": { m: "background" },
    655     "border-left": { m: "background" },
    656     "border-radius": { m: "background" },
    657     "bottom": { m: "visuren" },
    658     "box-shadow": { m: "background" },
    659     "color": { m: "color", a: "foreground" },
    660     "counter-increment": { m: "generate" },
    661     "counter-reset": { m: "generate" },
    662     "grid-definition-columns": { m: "grid" },
    663     "grid-definition-rows": { m: "grid" },
    664     "height": { m: "box" },
    665     "image-orientation": { m: "images" },
    666     "left": { m: "visuren" },
    667     "list-style": { m: "lists" },
    668     "min-height": { m: "box" },
    669     "min-width": { m: "box" },
    670     "opacity": { m: "color", a: "transparency" },
    671     "orphans": { m: "page" },
    672     "outline-offset": { m: "ui" },
    673     "padding": { m: "box", a: "padding1" },
    674     "padding-bottom": { m: "box" },
    675     "padding-left": { m: "box" },
    676     "padding-right": { m: "box" },
    677     "padding-top": { m: "box" },
    678     "page": { m: "page" },
    679     "quotes": { m: "generate" },
    680     "right": { m: "visuren" },
    681     "tab-size": { m: "text" },
    682     "text-indent": { m: "text" },
    683     "text-shadow": { m: "text-decor" },
    684     "top": { m: "visuren" },
    685     "unicode-range": { m: "fonts", a: "descdef-unicode-range" },
    686     "widows": { m: "page" },
    687     "width": { m: "box" },
    688     "z-index": { m: "visuren" }
    689 }
    690 
    691 /**
    692  * @param {string} propertyName
    693  * @return {!WebInspector.CSSMetadata}
    694  */
    695 WebInspector.CSSMetadata.keywordsForProperty = function(propertyName)
    696 {
    697     var acceptedKeywords = ["inherit", "initial"];
    698     var descriptor = WebInspector.CSSMetadata.descriptor(propertyName);
    699     if (descriptor && descriptor.values)
    700         acceptedKeywords.push.apply(acceptedKeywords, descriptor.values);
    701     if (propertyName in WebInspector.CSSMetadata._colorAwareProperties)
    702         acceptedKeywords.push.apply(acceptedKeywords, WebInspector.CSSMetadata._colors);
    703     return new WebInspector.CSSMetadata(acceptedKeywords);
    704 }
    705 
    706 /**
    707  * @param {string} propertyName
    708  * @return {?Object}
    709  */
    710 WebInspector.CSSMetadata.descriptor = function(propertyName)
    711 {
    712     if (!propertyName)
    713         return null;
    714     var unprefixedName = propertyName.replace(/^-webkit-/, "");
    715     var entry = WebInspector.CSSMetadata._propertyDataMap[propertyName];
    716     if (!entry && unprefixedName !== propertyName)
    717         entry = WebInspector.CSSMetadata._propertyDataMap[unprefixedName];
    718     return entry || null;
    719 }
    720 
    721 WebInspector.CSSMetadata.requestCSSShorthandData = function()
    722 {
    723     function propertyNamesCallback(error, properties)
    724     {
    725         if (!error)
    726             WebInspector.CSSMetadata.cssPropertiesMetainfo = new WebInspector.CSSMetadata(properties);
    727     }
    728     CSSAgent.getSupportedCSSProperties(propertyNamesCallback);
    729 }
    730 
    731 WebInspector.CSSMetadata.cssPropertiesMetainfoKeySet = function()
    732 {
    733     if (!WebInspector.CSSMetadata._cssPropertiesMetainfoKeySet)
    734         WebInspector.CSSMetadata._cssPropertiesMetainfoKeySet = WebInspector.CSSMetadata.cssPropertiesMetainfo.keySet();
    735     return WebInspector.CSSMetadata._cssPropertiesMetainfoKeySet;
    736 }
    737 
    738 // Weight of CSS properties based their usage on few popular websites https://gist.github.com/3751436
    739 WebInspector.CSSMetadata.Weight = {
    740     "-webkit-animation": 1,
    741     "-webkit-animation-duration": 1,
    742     "-webkit-animation-iteration-count": 1,
    743     "-webkit-animation-name": 1,
    744     "-webkit-animation-timing-function": 1,
    745     "-webkit-appearance": 1,
    746     "-webkit-background-clip": 2,
    747     "-webkit-border-horizontal-spacing": 1,
    748     "-webkit-border-vertical-spacing": 1,
    749     "-webkit-box-shadow": 24,
    750     "-webkit-font-smoothing": 2,
    751     "-webkit-transform": 1,
    752     "-webkit-transition": 8,
    753     "-webkit-transition-delay": 7,
    754     "-webkit-transition-duration": 7,
    755     "-webkit-transition-property": 7,
    756     "-webkit-transition-timing-function": 6,
    757     "-webkit-user-select": 1,
    758     "background": 222,
    759     "background-attachment": 144,
    760     "background-clip": 143,
    761     "background-color": 222,
    762     "background-image": 201,
    763     "background-origin": 142,
    764     "background-size": 25,
    765     "border": 121,
    766     "border-bottom": 121,
    767     "border-bottom-color": 121,
    768     "border-bottom-left-radius": 50,
    769     "border-bottom-right-radius": 50,
    770     "border-bottom-style": 114,
    771     "border-bottom-width": 120,
    772     "border-collapse": 3,
    773     "border-left": 95,
    774     "border-left-color": 95,
    775     "border-left-style": 89,
    776     "border-left-width": 94,
    777     "border-radius": 50,
    778     "border-right": 93,
    779     "border-right-color": 93,
    780     "border-right-style": 88,
    781     "border-right-width": 93,
    782     "border-top": 111,
    783     "border-top-color": 111,
    784     "border-top-left-radius": 49,
    785     "border-top-right-radius": 49,
    786     "border-top-style": 104,
    787     "border-top-width": 109,
    788     "bottom": 16,
    789     "box-shadow": 25,
    790     "box-sizing": 2,
    791     "clear": 23,
    792     "color": 237,
    793     "cursor": 34,
    794     "direction": 4,
    795     "display": 210,
    796     "fill": 2,
    797     "filter": 1,
    798     "float": 105,
    799     "font": 174,
    800     "font-family": 25,
    801     "font-size": 174,
    802     "font-style": 9,
    803     "font-weight": 89,
    804     "height": 161,
    805     "left": 54,
    806     "letter-spacing": 3,
    807     "line-height": 75,
    808     "list-style": 17,
    809     "list-style-image": 8,
    810     "list-style-position": 8,
    811     "list-style-type": 17,
    812     "margin": 241,
    813     "margin-bottom": 226,
    814     "margin-left": 225,
    815     "margin-right": 213,
    816     "margin-top": 241,
    817     "max-height": 5,
    818     "max-width": 11,
    819     "min-height": 9,
    820     "min-width": 6,
    821     "opacity": 24,
    822     "outline": 10,
    823     "outline-color": 10,
    824     "outline-style": 10,
    825     "outline-width": 10,
    826     "overflow": 57,
    827     "overflow-x": 56,
    828     "overflow-y": 57,
    829     "padding": 216,
    830     "padding-bottom": 208,
    831     "padding-left": 216,
    832     "padding-right": 206,
    833     "padding-top": 216,
    834     "position": 136,
    835     "resize": 1,
    836     "right": 29,
    837     "stroke": 1,
    838     "stroke-width": 1,
    839     "table-layout": 1,
    840     "text-align": 66,
    841     "text-decoration": 53,
    842     "text-indent": 9,
    843     "text-overflow": 8,
    844     "text-shadow": 19,
    845     "text-transform": 5,
    846     "top": 71,
    847     "unicode-bidi": 1,
    848     "vertical-align": 37,
    849     "visibility": 11,
    850     "white-space": 24,
    851     "width": 255,
    852     "word-wrap": 6,
    853     "z-index": 32,
    854     "zoom": 10
    855 };
    856 
    857 
    858 WebInspector.CSSMetadata.prototype = {
    859     /**
    860      * @param {string} prefix
    861      * @return {!Array.<string>}
    862      */
    863     startsWith: function(prefix)
    864     {
    865         var firstIndex = this._firstIndexOfPrefix(prefix);
    866         if (firstIndex === -1)
    867             return [];
    868 
    869         var results = [];
    870         while (firstIndex < this._values.length && this._values[firstIndex].startsWith(prefix))
    871             results.push(this._values[firstIndex++]);
    872         return results;
    873     },
    874 
    875     /**
    876      * @param {!Array.<string>} properties
    877      * @return {number}
    878      */
    879     mostUsedOf: function(properties)
    880     {
    881         var maxWeight = 0;
    882         var index = 0;
    883         for (var i = 0; i < properties.length; i++) {
    884             var weight = WebInspector.CSSMetadata.Weight[properties[i]];
    885             if (weight > maxWeight) {
    886                 maxWeight = weight;
    887                 index = i;
    888             }
    889         }
    890         return index;
    891     },
    892 
    893     _firstIndexOfPrefix: function(prefix)
    894     {
    895         if (!this._values.length)
    896             return -1;
    897         if (!prefix)
    898             return 0;
    899 
    900         var maxIndex = this._values.length - 1;
    901         var minIndex = 0;
    902         var foundIndex;
    903 
    904         do {
    905             var middleIndex = (maxIndex + minIndex) >> 1;
    906             if (this._values[middleIndex].startsWith(prefix)) {
    907                 foundIndex = middleIndex;
    908                 break;
    909             }
    910             if (this._values[middleIndex] < prefix)
    911                 minIndex = middleIndex + 1;
    912             else
    913                 maxIndex = middleIndex - 1;
    914         } while (minIndex <= maxIndex);
    915 
    916         if (foundIndex === undefined)
    917             return -1;
    918 
    919         while (foundIndex && this._values[foundIndex - 1].startsWith(prefix))
    920             foundIndex--;
    921 
    922         return foundIndex;
    923     },
    924 
    925     keySet: function()
    926     {
    927         if (!this._keySet)
    928             this._keySet = this._values.keySet();
    929         return this._keySet;
    930     },
    931 
    932     next: function(str, prefix)
    933     {
    934         return this._closest(str, prefix, 1);
    935     },
    936 
    937     previous: function(str, prefix)
    938     {
    939         return this._closest(str, prefix, -1);
    940     },
    941 
    942     _closest: function(str, prefix, shift)
    943     {
    944         if (!str)
    945             return "";
    946 
    947         var index = this._values.indexOf(str);
    948         if (index === -1)
    949             return "";
    950 
    951         if (!prefix) {
    952             index = (index + this._values.length + shift) % this._values.length;
    953             return this._values[index];
    954         }
    955 
    956         var propertiesWithPrefix = this.startsWith(prefix);
    957         var j = propertiesWithPrefix.indexOf(str);
    958         j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length;
    959         return propertiesWithPrefix[j];
    960     },
    961 
    962     /**
    963      * @param {string} shorthand
    964      * @return {?Array.<string>}
    965      */
    966     longhands: function(shorthand)
    967     {
    968         return this._longhands[shorthand];
    969     },
    970 
    971     /**
    972      * @param {string} longhand
    973      * @return {?Array.<string>}
    974      */
    975     shorthands: function(longhand)
    976     {
    977         return this._shorthands[longhand];
    978     }
    979 }
    980