我有一个用来创建模板的HTML类。我的课是这样的:
<?php
$page = 'TEST'HTML::dispense(':html');
$page->mainWrapper(':div') //creates a child object by using __call() and sets the "div" model
->id('mainWrapper') //sets id
->style('background','red') //adds a style
->text('blah') //adds a text
->addClass('someClass'); //adds a class
->someSpan(':span')
->addClass('spanClass')->addClass('someClass')
->style('font-size','12pt')
->style('border-bottom','1pt dashed black')
->style('background','red');
?>
这允许我快速开发html标记,而不用担心缺少字符或错误引用属性。所有东西都被缓存,我没有性能问题。
现在我想更进一步。在生产模式下,一切都工作得很好,但对于最终的输出,我想剥离所有内联的"样式"属性,并最小化它们,并将它们缓存在css文件中。现在,我有了一个函数,它循环遍历所有HTML对象,并根据标记、id和类聚合数据。我的问题是,一旦我有了整洁的css数组
$style['tag']['.class']['#id']['styleKey'] = styleValue
我如何修剪冗余的值,所以我留下了一个相关的css文件?缩小和压缩可以在后期进行。我现在想要的是比较值,并在转储它之前优化数组,以便所有具有相同标签/id/类的所有元素共同的'styleKeys'被分组在一起。
因此,在上面的例子中,例如,由于两个元素(div和span)共享样式为"background:red"和类为"someClass",我将使用"background:red"为"someClass"CSS规则如果你感兴趣的话,下面是我的"extractstyles"函数:
<?php
public static function extractStyles($element, array &$styles=array()){
if($element instanceof 'TEST'HTML){$element = $element->htmlData();}
$tag = isset($element['#acronym']) ? $element['#acronym'] : NULL;
$id = isset($element['#id']) ? '#'.$element['#id'] : NULL;
$classes = isset($element['#class']) ? $element['#class'] : NULL;
if(isset($element['#style']) && ($tag || $id || $class)){
$ref = &$styles;
if($id){if(!isset($ref[$id])){$ref[$id] = array();};$ref = &$ref[$id];}
if($classes){
if('is_array($classes)){$classes = '.'.implode('.',$classes);}
if(!isset($ref[$classes])){$ref[$classes] = array();};$ref = &$ref[$classes];
}
if($tag){if(!isset($ref[$tag])){$ref[$tag] = array();};$ref = &$ref[$tag];}
foreach($element[self::ATTRIBUTES]['#style'] as $style=>$value){
$ref[$style] = $value;
}
}
if(isset($element[self::CHILDREN]) && count($element[self::CHILDREN])){
foreach($element[self::CHILDREN] as $child){
self::extractStyles($child, $styles);
}
}
return $styles;
}
?>
任何指针都是非常受欢迎的…我真的迷路了。我甚至不知道我在寻找的东西是否可行。
如上所述,性能现在不是问题。如果可行,我会想办法优化它。此外,请不要链接到xCSS和其他框架,因为他们的工作对字符串和我的CSS创建为一个数组。提前感谢你能给我的任何帮助!
一阶优化是建立一个层次树。这个树中的父子关系是子关系是父关系的超集。此树的根节点是一个空样式(您不会显示它)。
因此如果你有
.parent {
background: red;
}
.childA {
background: red;
border: 1px solid black;
}
.childB {
background: red;
font-weight: 800;
}
父节点被设置为树中最小公分母。然后可以将其压缩为3个具有更少文本的类。子元素将包含路径中的所有类,如果你最初有<span class="childA">
,那么你将得到<span class="parent childA">
压缩后的类如下:
.parent {
background: red;
}
.childA {
border: 1px solid black;
}
.childB {
font-weight: 800;
}
关于id的说明,id总是最合适类的子类。因此如果你有
#menu {
background: red;
border: 1px solid black;
margin: 15px 40px;
color: white;
}
它将成为childda的子元素,并且它的css将缩减为
#menu {
margin: 15px 40px;
color: white;
}
并显示为<ul id="menu" class="parent childA">
要创建树,您需要一个对象来存储相同子对象的数组(递归地)和一个函数,当给定两个对象时,该函数可以确定它们的css是子集,相等还是超集,差异的数量,或者是否没有共性。
如果你不熟悉二叉搜索树,这将是一个很好的时间来钻研它,即使这将比那更复杂,这将是一个正确方向的良好开端。
第二级优化是确定嵌套子元素是否可以进一步减少对类的需求。例如,如果
<ul id="#menu">
中的所有<li>
样式相似,那么您可以为#menu li
创建规则
要做到这一点,您需要转到每个节点,并分析它的子节点。如果同一节点类型的所有子节点共享一个公共样式元素(使用上面的集合比较器),则提取公共集合元素作为父元素。差异变成了孩子。
让我们假设你有这样一个例子(注意它已经通过了第1步):
<ul id="menu" class="parent childA">
<li class="top menuli">Item</li>
<li class="menuli">Item</li>
<li class="menuli">Item</li>
<li class="menuli">Item</li>
<li class="bottom menuli">Item</li>
</ul>
我们注意到所有的<li>
都有一个共同的元素。menuli,这意味着我们可以消除这个在第1步中创建的类,并用#menu li
的平面规则代替它。为此,我们从每个子li中删除menuli类,并用#menu li
规则替换.menuli
规则。
我们的css改变如下:
#menu {
margin: 15px 40px;
color: white;
}
.menuli {
font-size: 30px;
font-weight: 800;
margin: 8px 0;
}
#menu {
margin: 15px 40px;
color: white;
}
#menu li {
font-size: 30px;
font-weight: 800;
margin: 8px 0;
}
html失去了类menuli
<ul id="menu" class="parent childA">
<li class="top">Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li class="bottom">Item</li>
</ul>
请记住,在搜索节点树时使用广度优先搜索,而不是深度优先搜索。如果你是激进的,你可以继续检查类似的标签在许多路径的第二级,一个常见的第二级搜索可能会发现类似的类#menu li a
或#container div p
等。如果你允许无限深度搜索,这就变成了NP困难问题。
希望这对你有帮助。如果这是你想要去的方向,我很乐意帮助更多关于集合比较器和可能的树搜索器的代码,尽管这要复杂得多。