专业汉语词典知识平台,分享汉字词语知识、历史文学知识解答!

励北网
励北网

css压缩方法,css压缩和格式化算法

来源:小易整编  作者:小易  发布时间:2022-12-26 05:10
摘要:css压缩方法,css压缩和格式化算法。本文是基于Java的CSS压缩和格式化的算法分析和实现文章。最近因为我个人开发的软件的很多用户对自定义CSS要求的呼声太高,所以,我决定在应用内增加一个自定义CSS的功能。因为要允许用户自己对CSS进...

css压缩方法,css压缩和格式化算法。本文是基于 Java 的 CSS 压缩和格式化的算法分析和实现文章。

最近因为我个人开发的软件的很多用户对自定义 CSS 要求的呼声太高,所以,我决定在应用内增加一个自定义 CSS 的功能。因为要允许用户自己对 CSS 进行编辑,所以我需要对 CSS 进行格式化的美化以提升用户体验。此外,在编辑完成之后为了减少存储空间的占用,通常需要对 CSS 进行压缩。所以,我这里写了一个压缩和一个格式化的算法,基于 Java 实现。

css压缩方法,css压缩和格式化算法

1、CSS 压缩

1.1 算法实现分析

对 CSS 进行压缩并不复杂,而且还有比较多的线上工具可以使用。首先,经过对 CSS 语法的分析,可知,要对 CSS 进行压缩,我们可以从下面几种字符着手:

空格

格式控制符,比如 '\n'、'\r' 和 '\t' 等

注释

对于注释和格式控制符,我们只需要在遇到的时候将其移除即可。而对于空格,需要注意并非所有的空格都是可以移除的,比如在 margin: 10px 10px 10px 10px 这样的语法中,空格分隔的四个属性分别对应于上下左右四个方向,如果移除空格可能会导致该属性失效。所以,经过分析,可以被移除空格的情形有如下几种,

连续存在的空格可以移除

对于用来指定 CSS 格式的符号,比如 '{'、'}' 和 ':' 等附近存在的空格可以移除

1.2 算法的实现和分析

经过上述分析,于是,具体的实现代码如下,

private static String compressCSS(String from) {    int validCharLength = 0;    char[] fromChars = from.toCharArray();    boolean inComment = false;    for (int i=0, len=fromChars.length; i<len; i++) {        char c = fromChars[i];        if (c == ' ' && (i == len-1 || i == 0 || isNormalSpace(fromChars[i+1]) || isNormalSpace(fromChars[i-1]))) {            continue;        }        if (c == '\n' || c == '\t' || c == '\r') {            continue;        }        if (i < len-1 && c == '/' && fromChars[i+1] == '*') { // begin of /*            inComment = true;            continue;        }        if (i > 0 && c == '/' && fromChars[i-1] == '*') { // end of */            inComment = false;            continue;        }        if (inComment) { // in /* and */            continue;        }        validCharLength++;    }    char[] chars = new char[validCharLength];    int index = 0;    inComment = false;    for (int i=0, len=fromChars.length; i<len; i++) {        char c = fromChars[i];        if (c == ' ' && (i == len-1 || i == 0 || isNormalSpace(fromChars[i+1]) || isNormalSpace(fromChars[i-1]))) {            continue;        }        if (c == '\n' || c == '\t' || c == '\r') {            continue;        }        if (i < len-1 && c == '/' && fromChars[i+1] == '*') { // begin of /*            inComment = true;            continue;        }        if (i > 0 && c == '/' && fromChars[i-1] == '*') { // end of */            inComment = false;            continue;        }        if (inComment) { // in /* and */            continue;        }        chars[index++] = c;    }    return new String(chars); } private static boolean isNormalSpace(char c) {    return c == '}' || c == ':' || c == ';' || c == ' ' || c == '{'; }

下面是对算法的详细说明,

对于数据结构的选择:因为压缩之前和压缩之后的文本长度不同,我们需要在计算的过程中动态调整数组的长度。一种方式是基于现有的集合数据结构,比如 ArrayList 和 LinkedList 等,但是因为 ArrayList 和 LinkedList 仅适用于包装类,而我们知道,包装类占用的内存存储空间比基本数据类型要大得多。所以,从内存占用角度,我们应该使用基本数据类型。对于基本数据类型,我们也可以使用 System.arrayCopy() 方法,在数组容量不足的时候进行动态扩容,但是这种方式实现起来难度要大得多。所以,这里采用了先计算需要的数组长度,得到长度之后直接申请需要的长度的数组,然后再对内容进行填充的方式实现。这样,从时间复杂度上将,两个遍历的复杂度都是 O(n),整体的复杂度是 O(n) + O(n) = O(n). 也就是,最终的时间复杂度是 O(n).

对注释的处理:这里在处理注释的时候的逻辑是,遇到了 / 的时候判断下一个字符是否为 * 或者上一个字符是否为 * 的方式来判断是否为注释的开始和结束。然后使用布尔类型变量记录当前遍历的内容是否为注释的内容,若为注释的内容则直接忽略,不加入到最终的数组中。

对控制符的处理:遇到控制符的时候只需要直接绕过即可。

对空格的处理:如之前的分析所示,在遇到空格的时候,我们可以通过判断它的上一个或者下一个字符来决定该空格是否可以被移除。也就是,比如 '{' 前后的字符是可以被移除的,因为它们只起到了格式美化,并没有实际作用。

2、CSS 格式化

2.1 算法实现分析

相比于压缩算法,格式化算法则复杂得多。这主要体现在,

需要自己判断一行是否结束,并且要在代码块 `{}` 内进行缩进处理。

一行结束不是非得有 ';' 或者 '}' 这样的明显的比较,也可能不加分号

此外,我们还需要考虑代码块嵌套的情形,需要进行多次缩进

这里对缩进的处理是,在遇到一行结束的时候主动给下一行增加缩进。这里用变量 regionCount 表示当前代码块的层次,比如一层的时候值是 1,两层的时候值是 2,以此类推。所以,下一行需要追加的缩进的空格的数量就是(这里默认使用两个空格进行缩进):

int spaceCount = regionCount * 2; while (spaceCount-- > 0) {    chars[index++] = ' '; }一行结束的标识符是 ;、} 或者 {,但也有可能不使用分号 ; 标识最后一行的结尾。所以,此时,我们需要根据 } 符号进行判断。因为不以分号结尾发生在所有样式语句的最后一条。此时,我们根据 } 的上一个字符进行判断,如果上一个字符是 ; 则表明之前已经针对 ; 处理过缩进了,如果不是,则表明上一行并非以分号结尾,所以没有处理过缩进,因此需要在当前行自己给自己追加缩进。不过,此时需要考虑一个特殊情形,就是上一行不是 CSS 样式,而是跟当前行一样是一个 },所以需要过滤这种情形,因此代码如下,if (i > 0 && fromChars[i-1] != ';' && fromChars[i-1] != '}') {    chars[index++] = '\n'; } // 加缩进 regionCount --; int spaceCount = regionCount * 2; while (spaceCount-- > 0) {    chars[index++] = ' '; }2.2 算法的实现和分析private static String formatCSS(String from) {    char[] fromChars = from.toCharArray();    int extendLength = 0;    int regionCount = 0;    for (int i=0, len=fromChars.length; i<len; i++) {        char c = fromChars[i];        if (c == '{') {            // '{' 前增加一个空格,后面增加一个 '\n'            extendLength += 2;            regionCount ++;            extendLength += (2 * regionCount);        } else if (c == '}') {            // 上一行结束,但是没有使用 ';'            if (i > 0 && fromChars[i-1] != ';'&& fromChars[i-1] != '}') {                extendLength += 1;            }            // '}' 后增加一个 '\n'            extendLength += 1;            regionCount --;            extendLength += (2 * regionCount);            if (regionCount > 0 && i < len-1 && fromChars[i+1] != '}') {                extendLength += (2 * regionCount);            }        }else if (c == ':' && regionCount > 0) {            extendLength += 1;        } else if (c == ';') {            extendLength += 1;            // 下一行仍有格式,追加两个空格            if (regionCount > 0 && i < len-1 && fromChars[i+1] != '}') {                extendLength += (2 * regionCount);            }        }    }    char[] chars = new char[extendLength + fromChars.length];    int index = 0;    regionCount = 0;    for (int i=0, len=fromChars.length; i<len; i++) {        char c = fromChars[i];        if (c == '{') {            // '{' 前增加一个空格,后面增加一个 '\n'            chars[index++] = ' ';            chars[index++] = c;            chars[index++] = '\n';            regionCount ++;            // 为下一行加缩进            int spaceCount = regionCount * 2;            while (spaceCount-- > 0) {                chars[index++] = ' ';            }        } else if (c == '}') {            // 上一行结束,但是没有使用 ';' 或者 '}',因为它们会自己追加 '\n'            if (i > 0 && fromChars[i-1] != ';' && fromChars[i-1] != '}') {                chars[index++] = '\n';            }            // 加缩进            regionCount --;            int spaceCount = regionCount * 2;            while (spaceCount-- > 0) {                chars[index++] = ' ';            }            chars[index++] = c;            // '}' 后增加一个 '\n'            chars[index++] = '\n';            // 如果下一行有样式,为下一行加缩进            if (regionCount > 0 && i < len-1 && fromChars[i+1] != '}') {                spaceCount = regionCount * 2;                while (spaceCount-- > 0) {                    chars[index++] = ' ';                }            }        } else if (c == ';') {            chars[index++] = c;            chars[index++] = '\n';            // 如果下一行有样式,为下一行加缩进            if (regionCount > 0 && i < len-1 && fromChars[i+1] != '}') {                int spaceCount = regionCount * 2;                while (spaceCount-- > 0) {                    chars[index++] = ' ';                }            }        } else if (c == ':' && regionCount > 0) {            // TODO rare cases 也有可能存在嵌套的 a:hover 的情形            chars[index++] = c;            chars[index++] = ' ';        } else {            chars[index++] = c;        }    }    return new String(chars); }算法的思路分析的时候已经分析了部分主要的实现,上述代码应该不难看懂。除了上面分析的之外,还要注意,对于 :,它可能用来标识标签的行为比如 a:hover,因此不能总是在后面追加空格。总结以上是对 Java 实现的 CSS 压缩和格式化算法的分析。对于我在应用中的使用场景,对算法的精度要求并不高,以上算法可以满足我的要求。其他的应用场景,建议酌情进行大量的样本测试之后再使用。



本文地址:百科问答频道 https://www.neebe.cn/wenda/886379.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!


百科问答
小编:小易整编
相关文章相关阅读
  • css布局技巧,css常见布局汇总

    css布局技巧,css常见布局汇总

    css布局技巧,css常见布局汇总要点速看网页开发基本思路:确定版心--》分析行模块--》分析列模块;如果一行当中有多个模块,一定要放在同一个父模块中;列模块首先可以先给宽高背景颜色,实例化盒子;常见布局:两栏/三栏/等高/粘带推荐flex...

  • css选择器有哪些,css选择器怎么用

    css选择器有哪些,css选择器怎么用

    css选择器有哪些,css选择器怎么用 CSS选择器又被称为CSS样式属性、CSS属性选择器,CSS中的“选择器”指明了“{}”中的“样式”的作用对象,也就是“样式”作用于网页中的哪些元素;常用选择器可分为标签名选择器、类选择器、id选择器...

  • CSS图片透明度怎么设置,CSS 透明度设置方法

    CSS图片透明度怎么设置,CSS 透明度设置方法

    CSS图片透明度怎么设置,CSS透明度设置方法怎样在CSS样式中设置背景的透明度怎样在CSS样式中设置背景的透明度,下面给出一个具体的实例。把类为box的层设为透明。 透明度设置 html...

  • css教程,0基础入门css教程

    css教程,0基础入门css教程

    通过使用CSS我们可以大大提升网页开发的工作效率!在我们的CSS教程中,您会学到如何使用CSS同时控制多重网页的样式和布局。1.CSS简介CSS是一种定义样式结构如字体、颜色、位置等的语言,被用于描述网页上的信息格式化和显示的方式。CSS样...

  • csshover怎么用,csshover用法教程

    csshover怎么用,csshover用法教程

    csshover怎么用,csshover用法教程1.实现效果在这里插入图片描述2.实现步骤定义一个宽高为300px的父容器.box{position:relative;width:300px;height:300px;}父容器中添加...

  • css样式表有哪几种,css样式表介绍

    css样式表有哪几种,css样式表介绍

    css样式表有哪几种,css样式表介绍层叠样式表(英文全称:CascadingStyleSheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰...

  • css3渐变属性,css3渐变教程

    css3渐变属性,css3渐变教程

    css3渐变属性,css3渐变教程好程序员web前端教程之CSS3渐变,CSS3渐变(gradient)可以让你在两个或多个指定的颜色之间显示平稳的过渡。以前,你必须使用图像来实现这些效果,现在通过使用CSS3的渐变(gradients)即...

  • 如何设置滚动条样式,CSS设置自定义滚动条样式

    如何设置滚动条样式,CSS设置自定义滚动条样式

    如何设置滚动条样式,CSS设置自定义滚动条样式你见过自定义滚动条样式的网站吗?是不是很想知道它们是怎么实现的?读完这篇文章,你会了解到使用CSS自定义滚动条样式的所有知识。在本教程中,你将:-学习能用来自定义滚动条样式的原生CSS属性-使用...

  • 周排行
  • 月排行
  • 年排行

精彩推荐