Files
Umbraco-CMS/src/Umbraco.Core/Models/Stylesheet.cs
Shannon Deminick 7ea87638f7 Updates all Entity models to use SetPropertyValueAndDetectChanges for setting all simple properties so that
tracking changes works the way it is supposed to. Creates a TracksChangesEntityBase class for any other entity
that wants to implement IRememberBeingDirty (now Entity inherits from this). Upgraded a bunch of other entities that
were not tracking changes properly.
2013-03-21 00:05:56 +06:00

161 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using Umbraco.Core.IO;
using Umbraco.Core.Models.Css;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a Stylesheet file
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class Stylesheet : File
{
public Stylesheet(string path) : base(path)
{
base.Path = path;
}
/// <summary>
/// Returns a flat list of <see cref="StylesheetProperty"/> objects
/// </summary>
/// <remarks>
/// Please note that the list is flattend by formatting single css selectors with
/// its value(s). Blocks in css @ rules are also flatten, but noted as part of an @ rule
/// by setting the <see cref="StylesheetProperty"/> property IsPartOfAtRule=true.
/// This is done to make the stylesheet usable in the backoffice.
/// </remarks>
[IgnoreDataMember]
public IEnumerable<StylesheetProperty> Properties
{
get
{
var properties = new List<StylesheetProperty>();
var parser = new CssParser(Content);
foreach (CssAtRule statement in parser.StyleSheet.Statements.Where(s => s is CssAtRule))
{
var cssBlock = statement.Block;
if(cssBlock == null) continue;
var cssValues = cssBlock.Values;
if(cssValues == null) continue;
properties.AddRange(FormatCss(cssBlock.Values, true));
}
var statements = parser.StyleSheet.Statements.Where(s => s is CssRuleSet);
properties.AddRange(FormatCss(statements, false));
return properties;
}
}
/// <summary>
/// Formats a list of statements to a simple <see cref="StylesheetProperty"/> object
/// </summary>
/// <param name="statements">Enumerable list of <see cref="ICssValue"/> statements</param>
/// <param name="isPartOfAtRule">Boolean indicating whether the current list of statements is part of an @ rule</param>
/// <returns>An Enumerable list of <see cref="StylesheetProperty"/> objects</returns>
private IEnumerable<StylesheetProperty> FormatCss(IEnumerable<ICssValue> statements, bool isPartOfAtRule)
{
var properties = new List<StylesheetProperty>();
foreach (CssRuleSet statement in statements)
{
foreach (var selector in statement.Selectors)
{
var declarations = new StringBuilder();
foreach (var declaration in statement.Declarations)
{
declarations.AppendFormat("{0}:{1};", declaration.Property, FormatCss(declaration.Value));
declarations.AppendLine("");
}
properties.Add(new StylesheetProperty(selector.Value.TrimStart('.', '#'), declarations.ToString()) { IsPartOfAtRule = isPartOfAtRule });
}
}
return properties;
}
/// <summary>
/// Formats a <see cref="CssValueList"/> to a single string
/// </summary>
/// <param name="valueList"><see cref="CssValueList"/> to format</param>
/// <returns>Value list formatted as a string</returns>
private string FormatCss(CssValueList valueList)
{
bool space = false;
var values = new StringBuilder();
foreach (CssString value in valueList.Values)
{
if (space)
{
values.Append(" ");
}
else
{
space = true;
}
values.Append(value);
}
return values.ToString();
}
/// <summary>
/// Boolean indicating whether the file could be validated
/// </summary>
/// <returns>True if file is valid, otherwise false</returns>
public override bool IsValid()
{
var dirs = SystemDirectories.Css;
//Validate file
var validFile = IOHelper.VerifyEditPath(Path, dirs.Split(','));
//Validate extension
var validExtension = IOHelper.VerifyFileExtension(Path, new List<string> {"css"});
return validFile && validExtension;
}
/// <summary>
/// Boolean indicating whether the file is valid css using a css parser
/// </summary>
/// <returns>True if css is valid, otherwise false</returns>
public bool IsFileValidCss()
{
var parser = new CssParser(Content);
try
{
var styleSheet = parser.StyleSheet;//Get stylesheet to invoke parsing
}
catch (Exception ex)
{
//Log exception?
return false;
}
return !parser.Errors.Any();
}
/// <summary>
/// Indicates whether the current entity has an identity, which in this case is a path/name.
/// </summary>
/// <remarks>
/// Overrides the default Entity identity check.
/// </remarks>
public override bool HasIdentity
{
get { return string.IsNullOrEmpty(Path) == false; }
}
}
}