ASP.NET, ASP.MVC - LESS CSS
Páči sa mi myšlienka Less CSS, preto som sa rozhodol urobiť alternatívu pre ASP.NET a ASP.MVC. Na internete som hľadal niečo podobné pre .NET, ale nič som poriadneho, malého a kompaktného nenašiel. A čo si človek nenapíše, to nemá.
Moja predstava Less
@border-radius(radius) { -moz-border-radius:@radius; border-radius:@radius; -webkit-border-radius:@radius }
@shadow(x,y,size,color) { -moz-box-shadow:@x @y @size @color; -webkit-box-shadow:@x @y @size @color; box-shadow:@x @y @size @color }
@red { color: Red }
@font-arial { font:normal 12px Arial }
@font-arial { font:normal 12px Arial }
@size { 12px }
div { @font-arial-neviem; @shadow(1px,1px,2px,#303030); }
p { @border-radius(5px); }
span { @red; @shadow(1px,1px,2px,rgba(1,1,1,0.5)); }
table { font-size:@size; }
Výsledok spracovania
div { font:normal 12px Arial; -moz-box-shadow:1px 1px 2px #303030;-webkit-box-shadow:1px 1px 2px #303030;box-shadow:1px 1px 2px #303030; }
p { -moz-border-radius:5px;border-radius:5px;-webkit-border-radius:5px; }
span { color: Red; -moz-box-shadow:1px 1px 2px rgba(1,1,1,0.5);-webkit-box-shadow:1px 1px 2px rgba(1,1,1,0.5);box-shadow:1px 1px 2px rgba(1,1,1,0.5); }
table { font-size:12px; }
Trieda obsahuje vlastnosť na zmenšenie veľkosti CSS, tu je výsledok:
div{font:normal 12px Arial;-moz-box-shadow:1px 1px 2px #303030;-webkit-box-shadow:1px 1px 2px #303030;box-shadow:1px 1px 2px #303030;}p{-moz-border-radius:5px;border-radius:5px;-webkit-border-radius:5px;}span{color:Red;-moz-box-shadow:1px 1px 2px rgba(1,1,1,0.5);-webkit-box-shadow:1px 1px 2px rgba(1,1,1,0.5);box-shadow:1px 1px 2px rgba(1,1,1,0.5);}table{font-size:12px;}
Trieda na spracovanie CSS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
public class Less
{
private class LessValue
{
private class LessParam
{
public string Name { get; set; }
public string Value { get; set; }
}
public int Index { get; set; }
public string Value { get; set; }
public string Name { get; set; }
public bool IsVariable { get; set; }
public bool IsFunction { get; set; }
public bool IsProblem { get; set; }
private string[] Split(string value)
{
var index = 0;
var l = new List<string>(5);
var skip = false;
var sb = new StringBuilder();
while (index < value.Length)
{
var c = value[index++];
if (c == '(' || c == '{')
skip = true;
else if (c == ')' || c == '}')
skip = false;
if (!skip && c == ',')
{
l.Add(sb.ToString());
sb.Clear();
}
else
sb.Append(c);
}
if (sb.Length > 0)
l.Add(sb.ToString());
return l.ToArray();
}
public string GetValue(LessValue less)
{
if (less == null)
return "";
if (IsVariable)
return "";
var value = "";
if (IsFunction)
{
var param = new List<LessParam>(5);
var beg = less.Value.IndexOf('(') + 1;
var end = less.Value.LastIndexOf(')');
foreach (var p in less.Value.Substring(beg, end - beg).Split(','))
{
param.Add(new LessParam() { Name = p.Trim() });
}
beg = Value.IndexOf('(') + 1;
end = Value.LastIndexOf(')');
var index = 0;
foreach (var p in Split(Value.Substring(beg, end - beg)))
param[index++].Value = p.Trim();
beg = less.Value.IndexOf('{') + 1;
end = less.Value.LastIndexOf('}');
index = 0;
var sb = new System.Text.StringBuilder();
foreach (var p in less.Value.Substring(beg, end - beg).Split(';'))
{
value = p.Trim();
if (string.IsNullOrEmpty(value))
continue;
foreach (var j in param)
value = value.Replace("@" + j.Name, j.Value);
if (sb.Length > 0)
sb.Append(';');
sb.Append(value);
}
return sb.ToString();
}
value = less.Value.Substring(less.Name.Length).Trim();
if ((value[0] == '{') && (value[value.Length - 1] == '}'))
value = value.Substring(1, value.Length - 2).Trim();
return value;
}
}
private static LessValue getValue(LessValue prev, string value)
{
var index = 0;
if (prev != null)
index = prev.Index + prev.Value.Length;
var beg = false;
var copy = false;
var param = 0;
var val = 0;
var sb = new System.Text.StringBuilder();
var less = new LessValue();
while (index < value.Length)
{
var c = value[index];
if (c == '@' && !less.IsFunction)
{
beg = true;
copy = true;
less.Index = index;
}
else if (beg)
{
var charindex = Convert.ToInt32(c);
if (charindex == 40)
param++;
else if (charindex == 41)
param--;
var next = false;
if (charindex == 123)
{
if (val == 0)
less.IsVariable = true;
val++;
next = true;
}
else if (charindex == 125)
{
if (val == 0)
{
index++;
continue;
}
val--;
next = true;
}
if (charindex == 32 || charindex == 41)
{
next = true;
}
else if (param == 0 && val == 0 && !next)
{
next = (charindex >= 65 && charindex <= 90) || (charindex >= 97 && charindex <= 122) || charindex == 45;
}
else if (param > 0 && val == 0)
{
next = charindex != 41;
less.IsFunction = true;
}
else if (val > 0 && param == 0)
{
next = true;
}
copy = next;
}
if (beg && copy)
{
sb.Append(c);
}
else if (beg)
{
if (copy)
sb.Append(c);
less.Value = sb.ToString().Trim();
if (less.IsFunction)
less.Name = less.Value.Substring(0, less.Value.IndexOf('(')).Trim();
else if (less.IsVariable)
less.Name = less.Value.Substring(0, less.Value.IndexOf('{')).Trim();
else
less.Name = less.Value.Trim();
if (less.Name == "@font-face")
less.IsProblem = true;
return less;
}
index++;
}
return null;
}
public static string Compile(string CSS, bool minify)
{
var l = new List<LessValue>(10);
var less = getValue(null, CSS);
if (less != null)
{
l.Add(less);
while (less != null)
{
less = getValue(less, CSS);
if (less != null)
l.Add(less);
}
}
if (l.Count > 0)
{
var variables = l.Where(n => n.IsVariable && !n.IsProblem).ToList();
foreach (var m in variables)
CSS = CSS.Replace(m.Value, "");
foreach (var m in l.Where(n => !n.IsVariable))
{
var value = m.GetValue(variables.Where(n => n.Name == m.Name).FirstOrDefault());
CSS = CSS.Replace(m.Value, value);
}
}
if (minify)
{
var reg1 = new Regex(@"\n|\s{2,}", System.Text.RegularExpressions.RegexOptions.Compiled);
var reg2 = new Regex(@"\s?\{\s{1,}");
var reg3 = new Regex(@"\s?\}\s{1,}");
var reg4 = new Regex(@"\s?\:\s{1,}");
var reg5 = new Regex(@"\s?\;\s{1,}");
return reg5.Replace(reg4.Replace(reg3.Replace(reg2.Replace(reg1.Replace(CSS, ""), "{"), "}"), ":"), ";");
}
return CSS.Trim();
}
}
Less.txt
1 kB
Handler pre ASP.NET a ASP.MVC
Posledná vec čo treba v Handleri urobiť je nastaviť Cacheovanie.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Handlers
{
public class CSS : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var path = "~" + context.Request.RawUrl.Replace('/', '\\');
context.Response.ContentType = "text/css";
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
if (System.IO.File.Exists(context.Server.MapPath(path)))
context.Response.BinaryWrite(System.Text.Encoding.UTF8.GetBytes(Less.Compile(System.IO.File.ReadAllText(context.Server.MapPath(path)), true)));
else
context.Response.StatusCode = 404;
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
Web.config
<system.webServer>
<handlers>
<add name="CSS" verb="*" path="/styles/*.css" type="Handlers.CSS" />
</handlers>
Peter Širka
pred 4 mesiacmi, 17.01.2012

A k tvojej implementacii, nevidim tam ani dedicnost ani kniznice na pracu s farbou, atd. Okrem toho to hlavne, teda podporu verzionovania s eternal cache by si mohol prihodit:)
A pokial sa jedna o mna, viac sa mi paci scss a pouzivam vs tool, ktory css skompiluje len raz http://visualstudiogallery.msdn.microsoft.com/2b96d16a-c986-4501-8f97-8008f9db141a