c#预处理css

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

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

测试效果图:

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

功能要求:

√  1.监控文件列表控件  列出需要监控的文件列表

√                      要求有右键删除功能

√                      休眠状态?文件在列表中 但暂时不进行监控

√  2.隐藏到托盘功能  一定要注意NotifyIcon的icon属性要选一张图不然没效果!!!

×  3.添加监控文件功能 批量功能要不要?  一个一个加吧

√  4.把rss文件编译为css文件

√  *[email protected]引入文件功能 引入变量文件

√  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();
        }

    }
}
时间: 2024-10-13 16:24:03

c#预处理css的相关文章

CSS预处理器之Less详解

本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. CSS 预处理器 为什么要有 CSS 预处理器 CSS基本上是设计师的工具,不是程序员的工具.在程序员的眼里,CSS是很头痛的事情,它并不像其它程序语言,比如说PHP.Javascript等等,有自己的变量.常量.条件语句以及一些编程语法,只是一行行单纯的属性描述,写起来相当的费事,而且代码难以组织和维护. 很自然的,有人就开始在想,能不能给CSS像其他程序语言一样,加

通用 CSS 笔记、建议与指导

在参与规模庞大.历时漫长且人手众多的项目时,所有开发者遵守如下规则极为重要: + **保持 CSS 的可维护性** + **保持代码清晰易懂** + **保持代码的可拓展性** 为了实现这一目标,我们要采用诸多方法. 本文档第一部分将探讨语法.格式以及 CSS 分析:第二部分将从方法论.思维框架以及编写与规划 CSS 的态度入手. ## 目录 * CSS 文档分析 * 总览 * 单一文件与多文件 * 目录 * 章节标题 * 代码顺序 * 规则解析 * 命名规范 * JavaScript 钩子 *

CSS Modules入门教程

为什么引入CSS Modules 或者可以这么说,CSS Modules为我们解决了什么痛点.针对以往我写网页样式的经验,具体来说可以归纳为以下几点: 全局样式冲突 过程是这样的:你现在有两个模块,分别为A.B,你可能会单独针对这两个模块编写自己的样式,例如a.css.b.css,看一下代码 // A.js import './a.css' const html = '<h1 class="text">module A</h1>' // B.js import

webpack的安装和使用

Webpack是什么 首先可以看下 官方文档 ,文档是最好的老师. Webpack是由Tobias Koppers开发的一个开源前端模块构建工具.它的基本功能是将以模块格式书写的多个JavaScript文件打包成一个文件,同时支持CommonJS和AMD格式.但让它与众不同的是,它提供了强大的loader API来定义对不同文件格式的预处理逻辑,从而让我们可以将CSS.模板,甚至是自定义的文件格式当做JavaScript模块来使用.Webpack 基于loader还可以实现大量高级功能,比如自动

Gulp开发教程

Building With Gulp =================== 原文地址 翻译出处 对网站资源进行优化,并使用不同浏览器测试并不是网站设计过程中最有意思的部分,但是这个过程中的很多重复的任务能够使用正确的工具自动完成,从而使效率大大提高,这是让很多开发者觉得有趣的地方. Gulp是一个构建系统,它能通过自动执行常见任务,比如编译预处理CSS,压缩JavaScript和刷新浏览器,来改进网站开发的过程.通过本文,我们将知道如何使用Gulp来改变开发流程,从而使开发更加快速高效. Wh

在Visual Studio 2015的Cordova项目中使用Gulp

之前一直是在vs 2013中使用Cordova来开发移动app(目前有iPad版/iPhone版/安卓版),准备到下一个milestone的时候升级到2015,这两天在尝试各种东西. 2015中的cordova项目和2013结构变化很大,所以需要一个手动迁移过程,这个过程之前已经有同事尝试过了,包括很多插件可能都要重新安装,不同插件的使用可能还有些不太一样. 这两天在研究如何在项目里使用gulp这个前端集成工具,vs 2015支持这个东西是一个非常大的利好,之前很多事情现在都可以自动来做了. g

node-sass报错解决方法

node-sass报错解决方法 node-sass报错解决方法 在Vue.js中,每一个vue文件都是一个组件,在.vue文件中可以将模板,脚本,样式写在一起,便于组织整个组件.在使用template,script时,编写css样式时,都进行的特别顺利,唯独当我想用sass来预处理css时,在style下使用lang='sass'一直报错. 在.vue中是这样的. <template > <div class="haha"> <p> keith +

Gulp开发教程(翻译)

Building With Gulp =================== 原文地址 翻译出处 原创翻译,有不当的地方欢迎指出.转载请指明出处.谢谢! 对网站资源进行优化,并使用不同浏览器测试并不是网站设计过程中最有意思的部分,但是这个过程中的很多重复的任务能够使用正确的工具自动完成,从而使效率大大提高,这是让很多开发者觉得有趣的地方. Gulp是一个构建系统,它能通过自动执行常见任务,比如编译预处理CSS,压缩JavaScript和刷新浏览器,来改进网站开发的过程.通过本文,我们将知道如何使

gulp初探

gulp初探 gulp是基于node.js的一个前端构建系统.它能通过自己主动运行常见任务,比方编译预处理CSS,压缩JavaScript和刷新浏览器.来改进站点的开发流程. gulp安装 1.假设没有安装node.js.请先去node管网安装最新版node.js; 2.安装了node后,在全局安装gulp: npm install -g gulp 3.然后.在项目里安装Gulp: npm install --save-dev gulp Gulp使用 如今我们创建一个Gulp任务来压缩JavaS