现在的位置: 首页 > Web开发 > .Net > Web开发 > 前端开发 > 正文

c#预处理css

2016年05月20日 .Net, 前端开发 ⁄ 共 10848字 ⁄ 字号 暂无评论

实现的功能:监控.rss文件变化(删除、重命名、内容变化)  并且处理为对应的.css文件

本人工作是web前端。less和sass的css预处理概念是非常好的,自己尝试了一下

测试效果图:

自己列的一个简单需求列表

功能要求:
 √  1.监控文件列表控件  列出需要监控的文件列表
 √                      要求有右键删除功能
 √                      休眠状态?文件在列表中 但暂时不进行监控
 √  2.隐藏到托盘功能  一定要注意NotifyIcon的icon属性要选一张图不然没效果!!!
 ×  3.添加监控文件功能 批量功能要不要?  一个一个加吧
 √  4.把rss文件编译为css文件
 √  *5.@引入文件功能 引入变量文件
 √  6.注释功能
 √  7.全部重新生成
格式定义:
 √  1.引入的文件中不得包含@文件(有也没作用) 因为不同于其他高级程序 css无需多级包含 把需要的复制过来 成为单独文件更方便
 √  2.一个变量 形如 $xxx : ... ;
 √      $与变量名间不得有空格  
 √      分号和冒号左右可以有空格
 √      支持一行多个变量
 √  3.只支持#开始的单行注释#
 √  4.使用方式 ($xxx)  或者 $xxx[^a-zA-Z0-9\-_]
 √  5.分号是关键字即使是url的字符串也不能使用
    
    新类
    变量定义:
 √    string inipath;// 配置文件的目录
 √    List<string> filelist = new List<string>();//要监控的文件列表
 √    List<FileSystemWatcher> watchs = new List<FileSystemWatcher>();//根据filelist获取对应的目录
    
    增
 √    void addOne(string filepath)    //处理添加的每一个需要监控文件
    删
 √    void deleteOne(string filepath)
    改
 √    void alterOne(string filepath)  //主要针对文件的重命名
    
    文件监控函数
 √        OnFileRenamed(){rss2css(e.FullPath.ToString());} 还得调用alterOne函数
 √        OnFileChanged(){rss2css(e.FullPath.ToString());}
 √        OnFileDeleted() 调用deleteOne函数
    
    
 √    void readini(string filepath) //读配置文件
 √    void writeini(string filepath)//程序关闭时写配置文件
    
    //根据rss文件路径编译文件生成css文件 依赖string preprocess(string text)
 √    void rss2css(string rssPath)
    //编译内容
 √    string preprocess(string text)
    
    界面:
 √  增加按钮:根据textBox调用addOne
 √  列表控件:显示filelist文件列表  允许右键删除事件(调用deleteOne)
    托盘事件:
 √      退出函数

主要引用:

         using System.IO;//FileWatch 文件读写
         using System.Text.RegularExpressions;//正则
         using Newtonsoft.Json;
         using Newtonsoft.Json.Linq;//json  要求framework4.5 要下载对应dll

这个watch.cs是一个类基本重要的函数都在这里

winform中会调用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;//FileWatch 文件读写
using System.Text.RegularExpressions;//正则
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;//json

namespace css_var2
{
    class Watchers
    {
        #region 成员变量
        //要编译的文件
        public List<string> files;
        //要监控的文件夹
        private List<FileSystemWatcher> folderWatchers;
        #endregion

        //构造函数
        public Watchers()
        {
            files = new List<string>();
            folderWatchers = new List<FileSystemWatcher>();
        }

        #region 成员方法
        //读配置文件
        public void readini(string filepath)
        {
            //配置文件保存之前需要监视的文件列表
            if (!File.Exists(filepath))
            {
                File.Create(filepath).Dispose();
            }
            else
            {
                FileStream fs = new FileStream(filepath, FileMode.Open);
                StreamReader m_streamReader = new StreamReader(fs);
                m_streamReader.BaseStream.Seek(0, SeekOrigin.Begin);// 从数据流中读取每一行,直到文件的最后一行
                string temp = "";
                temp = m_streamReader.ReadLine();
                while (temp != null)
                {
                    addOne(temp);
                    temp = m_streamReader.ReadLine();

                }
                m_streamReader.Close();
                fs.Close();
                //fs.Dispose();
            }

        }
        //程序关闭时写配置文件
        public void writeini(string filepath)
        {
            //清空
            FileStream fs1 = new FileStream(filepath, FileMode.Create, FileAccess.Write);
            fs1.SetLength(0);
            fs1.Close();
            //fs1.Dispose();
            //重写
            StreamWriter sw = new StreamWriter(filepath, true, Encoding.UTF8);
            for (int i = 0; i < files.Count; i++)
            {
                if (File.Exists(files[i]))
                    sw.WriteLine(files[i]);
            }
            sw.Flush();
            sw.Close();
        }
        //暂停监视功能
        public void startpause(bool bPause)
        {
            int n = folderWatchers.Count;
            for (int i = 0; i < n; i++)
            {
                folderWatchers[i].EnableRaisingEvents = bPause;
            }
        }
        //添加一个要编译的文件
        public void addOne(string filepath)
        {
            bool bFound = false;
            string temp = Path.GetExtension(filepath);
            int n=0;
            bFound = File.Exists(filepath);
            //要监控的文件必须存在 而且是自定义格式的rss拓展名
            if (bFound && temp.ToLower() == ".rss")
            {
                //检查文件是否已经加入过
                bFound = false;
                n = files.Count;
                for (int i = 0; i < n; i++)
                {
                    if (filepath == files[i])
                    {
                        bFound = true;
                        break;
                    }
                }
                if (bFound == false)
                {
                    //每加入一个新文件:文件列表添加文件名
                    files.Add(filepath);
                    //新加入的文件 的父目录是否已经进行了监视
                    n = folderWatchers.Count;
                    temp = Path.GetDirectoryName(filepath);
                    for (int i = 0; i < n; i++)
                    {
                        if (temp == folderWatchers[i].Path)
                        {
                            bFound = true;
                            break;
                        }
                    }
                    if (bFound == false)
                    {
                        FileSystemWatcher w = new FileSystemWatcher();
                        w.Path = temp;
                        w.Filter = "*.rss";
                        w.EnableRaisingEvents = true;
                        w.IncludeSubdirectories = false;
                        w.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                        w.Changed += OnFileChanged;
                        w.Renamed += OnFileRenamed;
                        w.Deleted += OnFileDelete;
                        folderWatchers.Add(w);
                    }
                }
            }
        }

        //删除一个要编译文件
        public void deleteOne(string filepath)
        {
            int n = folderWatchers.Count,
                l = files.Count;
            /*
            string temp = Path.GetDirectoryName(filepath);
            for (int i = 0; i < n; i++)
            {
                if (folderWatchers[i].Path == temp)
                {
                    folderWatchers.RemoveAt(i);
                    break;
                }
            }
            */
            for (int i = 0; i < l; i++)
            {
                if (files[i] == filepath)
                {
                    files.RemoveAt(i);
                    break;
                }
            }
        }

        //修改一个要编译文件的路径 
        public void alterOne(string oldpath,string filepath)
        {
            int n = files.Count,
                l = folderWatchers.Count;
            string tempNew = Path.GetDirectoryName(filepath),
                   tempOld = Path.GetDirectoryName(oldpath);
            for (int i = 0; i < n; i++)
            {
                if (files[i] == oldpath)
                {
                    files[i] = filepath;
                    break;
                }
            }
            for (int i = 0; i < l; i++)
            {
                if (folderWatchers[i].Path == tempOld)
                {
                    folderWatchers[i].Path = tempNew;
                    break;
                }
            }
        }

        //文件或目录重命名事件
        private void OnFileRenamed(object sender, RenamedEventArgs e)
        {
            //重新编译
            rss2css(e.FullPath.ToString());
            //修改监控对象的路径
            alterOne(e.OldFullPath.ToString(), e.FullPath.ToString());
        }
        //文件更改事件
        private void OnFileChanged(object sender, FileSystemEventArgs e)
        {
            //文件发生变化 重新编译生成文件
            rss2css(e.FullPath.ToString());
        }
        //文件删除事件
        private void OnFileDelete(object sender, FileSystemEventArgs e)
        {
            //删除监控对象
            deleteOne(e.FullPath.ToString());
        }
        //文件生成 - 调用preprocess函数将指定位置的rss文件编译 在同目录下生成css文件
        public void rss2css(string rssPath)
        {
            string temp = "",
                    res = "",
                    cssPath = Path.GetDirectoryName(rssPath) + "\\" + Path.GetFileNameWithoutExtension(rssPath) + ".css";
            bool bInFiles = false;
            for (int i = 0; i < files.Count; i++)
            {
                if (files[i] == rssPath)
                {
                    bInFiles = true;
                    break;
                }
            }
            if (bInFiles)
            {
                //读取
                try
                {
                    temp = File.ReadAllText(rssPath);
                }
                catch (Exception ee0)
                {

                }
                if (File.Exists(cssPath) == false)
                {
                    File.Create(cssPath).Dispose();
                }
                //写入
                try
                {
                    //清空
                    FileStream fs1 = new FileStream(cssPath, FileMode.Create, FileAccess.Write);
                    fs1.SetLength(0);
                    fs1.Close();
                    //重写
                    StreamWriter sw = new StreamWriter(cssPath, true, Encoding.UTF8);
                    res = preprocess(temp);
                    sw.Write(res);
                    sw.Flush();
                    sw.Close();
                }
                catch (Exception ee)
                {

                }
            }
        }
        //预处理 
        public string preprocess(string text)
        {
            string resStr = "";//要返回的字符串
            #region 定义要用到的变量
            bool bInclude = true,
                 bMain = false;
            List<string> includeFiles = new List<string>();
            //待处理的rss字符串
            string k = "",//($k)中的k字符串
                   v = "",//保存json[k].toString()
                   varStr = "",//变量部分
                   cssStr = "";//css部分
            //匹配包含的文件
            Regex include = new Regex(@"^\s*@(.+?)\r\n", RegexOptions.None);
            //匹配注释
            Regex comment = new Regex(@"^\s*#.+\r\n", RegexOptions.Singleline);
            //匹配一行:一个变量 形如 $xx:xxx;
            Regex getLine = new Regex(@".+\r\n", RegexOptions.Multiline);
            //将一个变量处理为 变量名:值 的数组
            Regex matchOne = new Regex(@"\s*\$([a-zA-Z0-9\-_]+)\s*[:]([^;]+)[;]");
            //匹配($xxx)
            Regex v2string = new Regex(@"\(\$(.+?)\)", RegexOptions.Multiline);
            //临时保存匹配结果
            Match match = null, t = null;
            //用于 分割变量部分和css部分的下标
            int index = 0;
            //变量json
            JObject json = new JObject();
            #endregion

            #region 1.分离变量和正文部分 解决了textbox中和文件中分离不一致的问题
            match = getLine.Match(text);//匹配含有一个变量的一行
            while (match.Groups[0].Value != "")
            {
                //正文还没开始 --> 匹配注释 --> 匹配到注释则跳过,没匹配到就匹配变量
                //先完成包含文件部分的匹配 将所有包含文件部分匹配完后 完成下一行的内容
                //正文开始时   --> 做变量替换

                #region 注释
                if (bMain == false)
                {
                    t = comment.Match(match.Groups[0].Value);
                    if (t.Groups[0].Value != "")
                    {
                        index = match.Index + t.Groups[0].Value.Length;
                        //匹配下一行
                        match = match.NextMatch();
                        if (match.Groups[0].Value == "")
                        {
                            bMain = true;
                        }
                        continue;
                    }
                }
                #endregion

                #region 先匹配包含文件部分
                bInclude = true;
                t = include.Match(match.Groups[0].Value);
                if (t.Groups[0].Value != "")
                {
                    includeFiles.Add(t.Groups[1].Value);
                }
                else
                {
                    bInclude = false;
                }
                if (bInclude)
                {
                    //匹配下一行
                    match = match.NextMatch();
                    if (match.Groups[0].Value == "")
                    {
                        bMain = true;
                    }
                    continue;
                }
                #endregion

                #region var
                t = matchOne.Match(match.Groups[0].Value);//一个变量按格式匹配 结果是长度为3的数组 原字符串 变量名 值
                
                if (t.Groups[0].Value == "")
                {
                    //变量匹配完成 获取css部分字符串
                    cssStr = text.Substring(index); break;
                }
                else
                {
                    //用于 分割变量部分与css部分
                    index = match.Index + t.Groups[0].Value.Length + 2;// \r\n 2个字符
                    while (t.Groups[0].Value != "")
                    {
                        //变量部分
                        varStr += t.Groups[0].Value + "\r\n";
                        t = t.NextMatch();
                    }
                    //匹配下一行
                    match = match.NextMatch();
                    if (match.Groups[0].Value == "")
                    {
                        bMain = true;
                    }
                }
                #endregion
            }
            #endregion

            //2.变量2json
            #region 2.1 读取@文件列表的文件 与varStr合并
            for (int i = 0; i < includeFiles.Count; i++)
            {
                if (File.Exists(includeFiles[i]))
                {
                    v = File.ReadAllText(includeFiles[i]);
                    varStr = v +"\r\n"+ varStr;
                }
            }
            #endregion
            #region  2.2 var2json
            match = getLine.Match(varStr);
            while (match.Groups[0].Value != "")
            {
                //注释
                t = comment.Match(match.Groups[0].Value);
                if (t.Groups[0].Value != "")
                {
                    //匹配下一行
                    match = match.NextMatch();
                    continue;
                }
                #region var2json
                t = matchOne.Match(match.Groups[0].Value);
                if (t.Groups[0].Value == "")
                {
                    //变量匹配完成
                    break;
                }
                else
                {
                    //变量2json
                    json[t.Groups[1].Value] = t.Groups[2].Value;

                    //匹配下一行
                    match = match.NextMatch();
                }
                #endregion
            }
            #endregion

            #region 3.处理变量值中的变量  $c_white:($white);
            foreach (var item in json)
                {
                    v = item.Value.ToString();
                    t = v2string.Match(v);
                    if (t.Groups[0].Value != "")
                    {
                        k = t.Groups[1].Value;
                        if (json.Property(k) != null)
                        {
                            v = v.Replace("($" + k + ")", json[k].ToString());
                        }
                        else
                        {
                            v = v.Replace("($" + k + ")", "");
                        }
                        json[item.Key] = v;
                    }
                }
            #endregion

            #region 4.cssstr变量替换
            resStr = cssStr;
            match = v2string.Match(cssStr);
            while (match.Groups.Count > 1)
            {
                if (match.Groups[0].Value != "")
                {
                    k = match.Groups[1].Value;
                    if (json.Property(k) != null)
                    {
                        v = json[k].ToString();
                    }
                    else
                    {
                        v = "";
                    }
                    resStr = resStr.Replace("($" + k + ")", v);
                }
                match = match.NextMatch();
            }
            #endregion

            return resStr;
        }
        #endregion
    }
}

winform的form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace css_var2
{
    public partial class Form1 : Form
    {
        private string iniPath = System.Environment.CurrentDirectory + @"\info.ini";
        private Watchers w1 = null;
        private bool CloseWin = false;
        public Form1()
        {
            InitializeComponent();
            
            this.ShowInTaskbar = false;
            this.notifyIcon1.Visible = true;
            //托盘菜单和事件
            MenuItem show = new MenuItem("显示");
            MenuItem quit = new MenuItem("退出");
            show.Click += new EventHandler(toNormal_Click);
            quit.Click += new EventHandler(quit_Click);

            this.notifyIcon1.ContextMenu = new System.Windows.Forms.ContextMenu();
            this.notifyIcon1.ContextMenu.MenuItems.Add(show);
            this.notifyIcon1.ContextMenu.MenuItems.Add(quit);

            //listBox contextmenu
            MenuItem del = new MenuItem("删除");
            del.Click += new EventHandler(delOne_Click);
            listBox1.ContextMenu = new System.Windows.Forms.ContextMenu();
            listBox1.ContextMenu.MenuItems.Add(del);
            //监控初始化
            w1 = new Watchers();
            w1.readini(iniPath);
            showFiles(ref w1.files);

            textBox2.Text = @"#test include
@C:\Users\sophsis\Desktop\test1.rss
#comment1
$c_white:color:($white);
#comment2
$c_black:color:($black);
#comment2
* {
    padding:0;
    margin:0;
    ($c_black);
}";
        }
        //将文件列表显示到 listbox中
        private void showFiles(ref List<string> lists)
        {
            int n = lists.Count;
            listBox1.Items.Clear();
            for (int i = 0; i < n; i++)
            {
                listBox1.Items.Add(lists[i]);
            }
        }
        //添加一个文件
        private void button1_Click(object sender, EventArgs e)
        {
            w1.addOne(textBox1.Text);
            textBox1.Clear();
            showFiles(ref w1.files);
        }

        //启动监视 暂停监视功能
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox cb = (CheckBox)sender;
            //暂停监视
            if (cb.Checked)
            {
                w1.startpause(false);
            }
            //启动监视
            else
            {
                w1.startpause(true);
            }
        }
        //测试预处理函数
        private void button2_Click(object sender, EventArgs e)
        {
            textBox3.Text = w1.preprocess(textBox2.Text);
        }
        //保存配置文件
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //托盘里关闭 才是真的关闭程序
            //
            if (this.CloseWin)
            {
                w1.writeini(iniPath);
            }
            else
            {
                e.Cancel = true;
                this.Hide();
            }
        }
        //删除一个监控
        private void delOne_Click(object sender, EventArgs e)
        {
            w1.deleteOne(listBox1.Items[listBox1.SelectedIndex].ToString());
            listBox1.Items.RemoveAt(listBox1.SelectedIndex);
        }
        //显示窗口事件
        private void toNormal_Click(object sender, EventArgs e)
        {
            this.Show();
        }
        //退出程序
        private void quit_Click(object sender, EventArgs e)
        {
            CloseWin = true;
            this.Close();
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            this.Show();
        }
        
    }
}