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