我正在尝试编写一个将背景的短手css声明转换为长手的函数。我写了下面的函数,但它有几个问题。一方面,它没有考虑background-color
可以是颜色值,例如black
,yellow
。此外,如果某些属性包含inherit
和none
,该怎么办?这是一个例子:
url('http://2.bp.blogspot.com/-h28qvOsfm1c/TaGyO_qAFcI/AAAAAAAAA9w/I7zPQLy0zVM/s640/funny-image.jpg') inherit inherit 0 0 #FFFFFF;
将上面的内容转换为CSS长手。这是我的功能,可以改进以涵盖其他情况吗?
function rewrite_background($b){
$long_hand = "";
$count = count($b);
for($i=0; $i < $count; $i++){
if(stripos($b[$i], '#') !== false){
$long_hand .= 'background-color: '.$b[$i].'; ';
unset($b[$i]);
}else if(stripos($b[$i], 'url') !== false){
$long_hand .= 'background-image: '.$b[$i].'; ';
unset($b[$i]);
}else if((stripos($b[$i], 'repeat') !== false) || (stripos($b[$i], 'no-repeat') !== false) || (stripos($b[$i], 'repeat-x') !== false) || (stripos($b[$i], 'repeat-y') !== false)){
$long_hand .= 'background-repeat: '.$b[$i].'; ';
unset($b[$i]);
}else if((stripos($b[$i], 'scroll') !== false) || (stripos($b[$i], 'fixed') !== false)){
$long_hand .= 'background-attachment: '.$b[$i].'; ';
unset($b[$i]);
}else{
// not recognized
}
}
$b = array_values($b);
if(isset($b[0])) $long_hand .= 'background-position: '.$b[0].' '.$b[1].';';
return $long_hand;
}
答案 0 :(得分:5)
此类将按任意顺序解析任何背景快捷方式属性,包括根据specs无效的背景快捷方式属性。例如,background: top top
被视为background-position: center top
。
完全支持所有颜色值,包括:rgb,rgba,hls,hlsa,不区分大小写的短格式十六进制(例如#fff),不区分大小写的长格式十六进制(例如#123Abc)和不区分大小写颜色名称。
现在支持 !important
。
inherit
似乎是最具挑战性的问题,但事实证明这是最简单的问题。对于这个属性,我提到http://reference.sitepoint.com/css/inheritvalue,其中指出:
当您使用背景等速记符号时,您无法混音 继承其他值。例如,以下背景 声明是错误的:
p { background: #fff inherit left top; }
... inherit必须是声明中唯一的值,因为有 根本没办法识别出属于哪个子属性的值 继承引用 - 毕竟,它在序列中并不是唯一的。在里面 上面的例子,继承变得模棱两可。
为了处理歧义,这个类只是忽略其他一切(除了!important)并将继承应用于所有属性,就像使用background: inherit
一样。
<?php
class CSSBackground
{
private $color_names = array(
'AliceBlue', 'AntiqueWhite', 'Aqua', 'Aquamarine', 'Azure',
'Beige', 'Bisque', 'Black', 'BlanchedAlmond', 'Blue',
'BlueViolet', 'Brown', 'BurlyWood', 'CadetBlue', 'Chartreuse',
'Chocolate', 'Coral', 'CornflowerBlue', 'Cornsilk', 'Crimson',
'Cyan', 'DarkBlue', 'DarkCyan', 'DarkGoldenRod', 'DarkGray',
'DarkGrey', 'DarkGreen', 'DarkKhaki', 'DarkMagenta',
'DarkOliveGreen', 'Darkorange', 'DarkOrchid', 'DarkRed',
'DarkSalmon', 'DarkSeaGreen', 'DarkSlateBlue', 'DarkSlateGray',
'DarkSlateGrey', 'DarkTurquoise', 'DarkViolet', 'DeepPink',
'DeepSkyBlue', 'DimGray', 'DimGrey', 'DodgerBlue', 'FireBrick',
'FloralWhite', 'ForestGreen', 'Fuchsia', 'Gainsboro',
'GhostWhite', 'Gold', 'GoldenRod', 'Gray', 'Grey', 'Green',
'GreenYellow', 'HoneyDew', 'HotPink', 'IndianRed', 'Indigo',
'Ivory', 'Khaki', 'Lavender', 'LavenderBlush', 'LawnGreen',
'LemonChiffon', 'LightBlue', 'LightCoral', 'LightCyan',
'LightGoldenRodYellow', 'LightGray', 'LightGrey', 'LightGreen',
'LightPink', 'LightSalmon', 'LightSeaGreen', 'LightSkyBlue',
'LightSlateGray', 'LightSlateGrey', 'LightSteelBlue', 'LightYellow',
'Lime', 'LimeGreen', 'Linen', 'Magenta', 'Maroon',
'MediumAquaMarine', 'MediumBlue', 'MediumOrchid', 'MediumPurple',
'MediumSeaGreen', 'MediumSlateBlue', 'MediumSpringGreen',
'MediumTurquoise', 'MediumVioletRed', 'MidnightBlue', 'MintCream',
'MistyRose', 'Moccasin', 'NavajoWhite', 'Navy', 'OldLace', 'Olive',
'OliveDrab', 'Orange', 'OrangeRed', 'Orchid', 'PaleGoldenRod',
'PaleGreen', 'PaleTurquoise', 'PaleVioletRed', 'PapayaWhip',
'PeachPuff', 'Peru', 'Pink', 'Plum', 'PowderBlue', 'Purple', 'Red',
'RosyBrown', 'RoyalBlue', 'SaddleBrown', 'Salmon', 'SandyBrown',
'SeaGreen', 'SeaShell', 'Sienna', 'Silver', 'SkyBlue', 'SlateBlue',
'SlateGray', 'SlateGrey', 'Snow', 'SpringGreen', 'SteelBlue', 'Tan',
'Teal', 'Thistle', 'Tomato', 'Turquoise', 'Violet', 'Wheat', 'White',
'WhiteSmoke', 'Yellow', 'YellowGreen'
);
private $m_bgcolor = 'transparent';
private $m_bgimage = 'none';
private $m_bgrepeat = 'repeat';
private $m_bgattachment = 'scroll';
private $m_bgposition = '0% 0%';
private $m_bgimportant = false;
private $m_bg;
public function __construct($bg)
{
// reformat array names for efficient pattern matching
$this->color_names = '/\b('.implode('|',$this->color_names).')\b/i';
$this->m_bg = $bg; // save original
$bg = $this->parse_important($bg);
$bg = $this->parse_inherit($bg);
$bg = $this->parse_color($bg);
$bg = $this->parse_image($bg);
$bg = $this->parse_repeat($bg);
$bg = $this->parse_attachment($bg);
$bg = $this->parse_position($bg);
}
public function original()
{
return $this->m_bg;
}
public function color()
{
return $this->m_bgcolor;
}
public function image()
{
return $this->m_bgimage;
}
public function repeat()
{
return $this->m_bgrepeat;
}
public function attachment()
{
return $this->m_bgattachment;
}
public function position()
{
return $this->m_bgposition;
}
public function important()
{
return $this->m_bgimportant;
}
private function parse_important($c)
{
// check for !important
if (preg_match('/!important/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgimportant = true ;
}
return $c;
}
private function parse_inherit($c)
{
// check for !important
if (preg_match('/inherit/i', $c, $m))
{
$this->m_bgcolor = $this->apply_important('inherit');
$this->m_bgimage = $this->apply_important('inherit');
$this->m_bgrepeat = $this->apply_important('inherit');
$this->m_bgattachment = $this->apply_important('inherit');
$this->m_bgposition = $this->apply_important('inherit');
$c = '';
}
return $c;
}
private function parse_color($c)
{
// check for hexit color value
if (preg_match('/#([[:xdigit:]]{3}){1,2}/', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgcolor = $this->apply_important($m[0]);
}
// check for rgb color value
elseif (preg_match('/rgb\(\d{0,3}\,\d{0,3},\d{0,3}\)/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgcolor = $this->apply_important($m[0]);
}
// check for rgba color value
elseif (preg_match('/rgba\(\d{0,3}%?\,\d{0,3}%?,\d{0,3}%?\,\d(\.\d)?\)/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgcolor = $this->apply_important($m[0]);
}
// check for hls color value
elseif (preg_match('/hls\(\d{0,3}\,\d{0,3}%,\d{0,3}%\)/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgcolor = $this->apply_important($m[0]);
}
// check for hlsa color value
elseif (preg_match('/hlsa\(\d{0,3}\,\d{0,3}%,\d{0,3}%\,\d(\.\d)?\)/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgcolor = $this->apply_important($m[0]);
}
// check for transparent
elseif (preg_match('/transparent/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgcolor = $this->apply_important('transparent');
}
// check for color names
elseif (preg_match($this->color_names, $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgcolor = $this->apply_important($m[0]);
}
return $c;
}
private function parse_image($c)
{
// check for double word positions
if (preg_match('/url\((.*?)\)|none/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
if (isset($m[1]))
{
$m[0] = str_replace($m[1], urlencode($m[1]), $m[0]);
}
$this->m_bgimage = $this->apply_important($m[0]);
}
return $c;
}
private function parse_repeat($c)
{
// check for repeat values
if (preg_match('/\b(repeat-x|repeat-y|no-repeat|repeat)\b/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgrepeat = $this->apply_important($m[0]);
}
return $c;
}
private function parse_attachment($c)
{
// check for repeat values
if (preg_match('/scroll|fixed/i', $c, $m))
{
$c = str_replace($m[0], '', $c);
$this->m_bgattachment = $this->apply_important($m[0]);
}
return $c;
}
private function parse_position($c)
{
// check for position values
if (preg_match_all('/left|right|center|top|bottom|-?\d+([a-zA-Z]{2}|%?)/i', $c, $m))
{
$horz = '0%';
$vert = '0%';
if (!isset($m[0][1]))
{
$x = strtolower($m[0][0]);
switch ($x)
{
case 'top':
case 'bottom':
$horz = 'center';
$vert = $x;
break;
case 'left':
case 'right':
case 'center':
$horz = $x;
$vert = 'center';
break;
default:
$horz = is_numeric($x) ? "{$x}px" : $x;
$vert = 'center';
}
}
else
{
$horz = strtolower($m[0][0]);
$vert = strtolower($m[0][1]);
if (($horz === $vert) && in_array($horz, array('left','right')))
{
$vert = 'center';
}
if (($horz === $vert) && in_array($horz, array('top','bottom')))
{
$horz = 'center';
}
if ($horz === 'top' || $horz === 'bottom')
{
list($horz,$vert) = array($vert,$horz);
}
if ($vert === 'left' || $vert === 'right')
{
list($horz,$vert) = array($vert,$horz);
}
}
$this->m_bgposition = $this->apply_important("$horz $vert");
}
return $c;
}
private function apply_important($prop)
{
return $prop . ($this->m_bgimportant ? ' !important' : '');
}
}
?>
<?php
header('Content-type: text/plain');
$bg = 'url("chess.png") gray 50% repeat fixed';
$cssbg = new CSSBackground($bg);
echo "background: ", $cssbg->original(), "\n\n";
echo "background-color: ", $cssbg->color(), "\n";
echo "background-image: ", $cssbg->image(), "\n";
echo "background-repeat: ", $cssbg->repeat(), "\n";
echo "background-attachment: ", $cssbg->attachment(), "\n";
echo "background-position: ", $cssbg->position(), "\n\n";
echo "!important applied: ", $cssbg->important() ? 'true' : 'false', "\n";
?>
本课程是通过对w3c specifications for the CSS background property的广泛分析而开发的。其他CSS属性需要相同的分析处理。
答案 1 :(得分:1)
我认为你在这里做的最好是建立一个近似的近似,因为你的程序必须完全理解CSS才能完全转换它,正则表达式不能完成任务。您需要一个真正的解析库。但首先,有一个非常好的教程,使用Coco / R解析器来处理CSS:http://www.codeproject.com/KB/recipes/CSSParser.aspx它将使您更好地了解问题的范围。
这里还有一个用于CSS解析的PHP类http://www.phpclasses.org/package/1289-PHP-CSS-parser-class.html#download,但我对此并没有太大的期望。
答案 2 :(得分:1)
不是使用stripos
搜索$ b而是根据结果不为FALSE分配CSS long-hand属性,为什么不按顺序进行?每次在将$ b属性传递给函数之前都可以使用set模式:
$b[0]=background-attachment;
$b[1]=background-color;
$b[2]=background-image;
$b[3]=background-position;
$b[4]=background-repeat;
这意味着你需要将你的简写重新排列成:
$b=array(inherit, #fff, url('example.jpg'), 0 0, inherit);
因此,您可以处理任何属性值(甚至是'inherit'和'none') - 您只需确保始终保持正确的序列,并且不要错过任何属性,否则数组键会出错。您可以在另一个PHP函数中轻松地将CSS颜色名称转换为十六进制值(使用list of all the CSS names),或者您可以使用this JavaScript function。
答案 3 :(得分:0)
我建议你找一个有很多regexp经验的人给你写一个强大的匹配字符串。
尽管你可以假设:
,但你现在的方式会遇到真正的问题url(。*)始终是背景图片
#(。{3})(。{3})?总是一种颜色(但你可能有其他的词与这里的任何其他匹配都不匹配,也是颜色)
([1-9] [0-9]%| [0-9] [0-9] +(px | em)| 0 | inherit | top | bottom | center | left | right)是背景位置(以及其中的一个或两个)
(重复|重复-x |重复-y |无重复|继承)始终为背景重复
请记住,他们可能属于众多订单之一。
答案 4 :(得分:-1)
在PHP中完成你想做的事情几乎是不可能的。你得到的最好的是一个非常接近的不完美的情况,例如,你的不支持rgb,rgba,hsl,hsla颜色格式,这是有效的。
你应该做的是找到一个好的php css parser,并使用它。