private static List<NameValueProperty> PrefixProperty(NameValueProperty prop) { var ret = new List<NameValueProperty>(); var possibleMatches = new List<Tuple<Prefix, string>>(); foreach (var val in Enum.GetValues(typeof(Prefix))) { possibleMatches.Add(Tuple.Create((Prefix)val, prop.Name)); } foreach (var match in possibleMatches) { Prefixer generate; if (KnownPrefixes.TryGetValue(match, out generate)) { var perBrowserValue = generate(match.Item1, prop); ret.AddRange(perBrowserValue); } } // No prefixed versions found if (ret.Count == 0) { ret.Add(prop); return ret; } // Just to make testing easier ret = ret.OrderBy(r => r.Name).ToList(); ret.Add(prop); return ret; }
/// <summary> /// border-radius and -moz-border-radius differ. /// /// -webkit-border-radius: a b; /// is equivalent to /// -webkit-top-left-border-radius: a b; /// -webkit-top-right-border-radius: a b; /// etc. /// /// border-radius: a b; /// is equivalent to /// border-top-left-radius: a; /// border-top-right-radius: b; /// border-bottom-right-radius: a; /// border-bottom-left-radius: b; /// /// This is only true if border-radius has two values; for all other configurations they are equivalent /// (at least so far as I can tell). /// </summary> private static IEnumerable<NameValueProperty> WebkitBorderRadius(Prefix pre, NameValueProperty borderRadius) { if (borderRadius.Name != "border-radius") throw new InvalidOperationException("Prefixer only valid for border-radius property"); if (pre != Prefix.WEBKIT) throw new InvalidOperationException("Prefixer only valid for WEBKIT prefix"); var asCompound = borderRadius.Value as CompoundValue; if (asCompound == null || asCompound.Values.Count() != 2) { return Simple(pre, borderRadius); } var ret = new List<NameValueProperty>(); var tlbr = asCompound.Values.ElementAt(0); var trbl = asCompound.Values.ElementAt(1); ret.Add(new NameValueProperty("-webkit-border-top-left-radius", tlbr)); ret.Add(new NameValueProperty("-webkit-border-top-right-radius", trbl)); ret.Add(new NameValueProperty("-webkit-border-bottom-left-radius", trbl)); ret.Add(new NameValueProperty("-webkit-border-bottom-right-radius", tlbr)); return ret; }
/// <summary> /// Handles a straight up name change. /// /// If a browser implements a property as "-pre-foo" but the spec comes down to "bar", /// this let's use build a Prefixer that will map "bar: x' to "-pre-foo: x" /// </summary> private static Prefixer Rename(string newName) { return (pre, prop) => { var renamed = new NameValueProperty( newName, prop.Value ); return Simple(pre, renamed); }; }
/// <summary> /// For the display: box; property, changes the value to display: -prefix-box; /// </summary> private static IEnumerable<NameValueProperty> PrefixBox(Prefix pre, NameValueProperty display) { if(!display.Name.Equals("display", StringComparison.InvariantCultureIgnoreCase)) throw new InvalidOperationException("Prefixer only valid on display property"); var asStr = display.Value as StringValue; if (asStr == null) return Enumerable.Empty<NameValueProperty>(); if (asStr.Value.Equals("box", StringComparison.InvariantCultureIgnoreCase)) { return new [] { new NameValueProperty( "display", new StringValue("-"+pre.ToString().ToLowerInvariant()+"-box") ) }; } return Enumerable.Empty<NameValueProperty>(); }
/// <summary> /// Old versions of IE have two different syntax's for opacity: /// - -ms-filter: progid:DXImageOhKillMeNow(Opacity=percent) /// - filter: alpha(opacity=percent) /// </summary> private static IEnumerable<NameValueProperty> IEOpacity(Prefix pre, NameValueProperty opacity) { if (!opacity.Name.Equals("opacity", StringComparison.InvariantCultureIgnoreCase)) throw new InvalidOperationException("Prefix only valid on opacity property"); if (pre != Prefix.MS) throw new InvalidOperationException("Prefixer only valid for MS prefix"); var asNumber = opacity.Value as NumberValue; if (asNumber == null || asNumber is NumberWithUnitValue) return Enumerable.Empty<NameValueProperty>(); var percent = decimal.Round(asNumber.Value * 100, 0); return new[] { new NameValueProperty("filter", new StringValue("progid:DXImageTransform.Microsoft.Alpha(Opacity=" + percent + ")")) }; }
/// <summary> /// Mozilla supports prefixed versions of background-clip & background-origin /// that accepts alternate versions of padding-box and border-box; padding and border respectively. /// </summary> private static IEnumerable<NameValueProperty> MozBackgroundBoxAlt(Prefix pre, NameValueProperty backgroundX) { if (pre != Prefix.MOZ) throw new InvalidOperationException("Prefixer only valid for MOZ"); var asStr = backgroundX.Value as StringValue; if (asStr == null) return Enumerable.Empty<NameValueProperty>(); if (asStr.Value.Equals("padding-box", StringComparison.InvariantCultureIgnoreCase)) { return Simple( pre, new NameValueProperty(backgroundX.Name, new StringValue("padding")) ); } if(asStr.Value.Equals("border-box", StringComparison.InvariantCultureIgnoreCase)) { return Simple( pre, new NameValueProperty(backgroundX.Name, new StringValue("border")) ); } return Enumerable.Empty<NameValueProperty>(); }
/// <summary> /// Webkit's prefixed background-size differs from the spec /// in that a single value (background-size: X) is treated like (background-size: X X). /// /// It should be treated as (background-size: X auto), this detects and inserts that case. /// /// In the case where two values are passed, the prefixed version matches the final spec. /// </summary> private static IEnumerable<NameValueProperty> WebkitBackgroundSize(Prefix pre, NameValueProperty backgroundSize) { var asMulti = backgroundSize.Value as CompoundValue; if (asMulti != null) return Simple(pre, backgroundSize); var newValue = new CompoundValue(backgroundSize.Value, new StringValue("auto")); return Simple(pre, new NameValueProperty(backgroundSize.Name, newValue)); }
private static NameValueProperty CacheBreakProperty(NameValueProperty prop) { return new NameValueProperty(prop.Name, CacheBreakValue(prop.Value), prop.Start, prop.Stop, prop.FilePath); }