将CSS字体简写转换为长手

时间:2011-07-15 13:55:52

标签: php css

给出一个字体CSS字符串,如:

font:italic bold 12px/30px Georgia, serif;

font:12px verdana;

我想将其转换为长手形式,即:

font-style: italic; font-weight: bold;

这是我悲惨的尝试:http://pastebin.com/e3KdMvGT

但当然它不适用于第二个例子,因为它期望事情有序,我该如何改进呢?

4 个答案:

答案 0 :(得分:5)

这是一个应该完成工作的功能。问题在于font-style,font-variant和font-weight属性以及值“normal”,您可以在css specs[[ <'font-style'> || <'font-variant'> || <'font-weight'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit)中阅读。

$testStrings = array('12px/14px sans-serif',
                     '80% sans-serif',
                     'x-large/110% "New Century Schoolbook", serif',
                     'x-large/110% "New Century Schoolbook"',
                     'bold italic large Palatino, serif ',
                     'normal small-caps 120%/120% fantasy',
                     'italic bold 12px/30px Georgia, serif',
                     '12px verdana');

foreach($testStrings as $font){
  echo "Test ($font)\n<pre>
";
  $details = extractFull($font);
  print_r($details);
  echo "
</pre>";
}


function extractFull($fontString){
  // Split $fontString. The only area where quotes should be found is around font-families. Which are at the end.
  $parts = preg_split('`("|\')`', $fontString, 2, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

  $chunks = preg_split('` `', $parts[0], NULL, PREG_SPLIT_NO_EMPTY);
  if(isset($parts[1])){
    $chunks[] = $parts[1] . $parts[2];
  }

  $details = array();
  $next = -1;

  // Manage font-style / font-variant / font-weight properties
  $possibilities = array();
  $fontStyle = array('italic', 'oblique');
  $fontVariant = array('small-caps');
  $fontWeight = array('bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900');

  // First pass on chunks 0 to 2 to see what each can be
  for($i = 0; $i < 3; $i++){
    $possibilities[$i] = array();
    if(!isset($chunks[$i])){
      if($next == -1){
        $next = $i;
      }
      continue;
    }
    if(in_array($chunks[$i], $fontStyle)){
      $possibilities[$i] = 'font-style';
    }
    else if(in_array($chunks[$i], $fontVariant)){
      $possibilities[$i] = 'font-variant';
    }
    else if(in_array($chunks[$i], $fontWeight)){
      $possibilities[$i] = 'font-weight';
    }
    else if($chunks[$i] == 'normal'){
      $possibilities['normal'] = 1;
    }
    else if($next == -1){
      // Used to know where other properties will start at
      $next = $i;
    }
  }

  // Second pass to determine what real properties are defined
  for($i = 0; $i < 3; $i++){
    if(!empty($possibilities[$i])){
      $details[$possibilities[$i]] = $chunks[$i];
    }
  }

  // Third pass to set the properties which have to be set as "normal"
  if(!empty($possibilities['normal'])){
    $properties = array('font-style', 'font-variant', 'font-weight');
    foreach($properties as $property){
      if(!isset($details[$property])){
        $details[$property] = 'normal';
      }
    }
  }

  if(!isset($chunks[$next])){
    return $details;
  }

  // Extract font-size and line height
  if(strpos($chunks[$next], '/')){
    $size = explode('/', $chunks[$next]);
    $details['font-size'] = $size[0];
    $details['line-height'] = $size[1];
    $details['font-family'] = $chunks[$next+1];
  }
  else if(preg_match('`^-?[0-9]+`', $chunks[$next]) || 
          in_array($chunks[$next], array('xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', 'larger', 'smaller'))){
    $details['font-size'] = $chunks[$next];
    $details['font-family'] = $chunks[$next+1];
  }
  else{
    $details['font-family'] = $chunks[$next];
  }

  return $details;
}

答案 1 :(得分:2)

这是我的尝试

function rewriteFont($short) { 
    $short = str_replace("font:","",$short);
    $values = explode(" ", $short);
    $length = count($values);
    $familyLength = 0;

    for($i = 0; $i < $length; $i++) {
        $currentValue = $values[$i];
        if($currentValue == 'italic' || $currentValue == 'oblique' ) { 
            echo "font-style:{$currentValue};";
        } 
        else if($currentValue == 'small-caps') { 
            echo "font-variant:{$currentValue};";
        }
        else if ($currentValue == 'bold' || $currentValue == 'bolder' || $currentValue == 'lighter' || is_numeric($currentValue) ) {
            echo "font-weight:{$currentValue};";
        }
        else if (strpos($currentValue, "px") || strpos($currentValue, "em") || strpos($currentValue, "ex")|| strpos($currentValue, "pt")
        || strpos($currentValue, "%") || $currentValue == "xx-small" || $currentValue == "x-small" || $currentValue == "small"
        || $currentValue == "medium" || $currentValue == "large" || $currentValue == "x-large" || $currentValue == "xx-large") {
            $sizeLineHeight = explode("/", $currentValue);
            echo "font-size:{$sizeLineHeight[0]};";
            if(isset($sizeLineHeight[1])) {
                echo "line-height:{$sizeLineHeight[1]};";
            }
        }
        else {
            if($familyLength == 0) { 
                echo "font-family:{$currentValue} ";
            }
            else {
                echo $currentValue; 
            }
            $familyLength++;
        }   
    }

}

答案 2 :(得分:2)

遵循规范,我会做以下代码。它适用于规范中的所有示例。你可以在这里看到它:http://codepad.viper-7.com/ABhc22

function font($s){
    $fontStyle      = array('normal', 'italic', 'oblique', 'inherit');
    $fontVariant        = array('normal', 'small-caps','inherit');
    $fontSize           = array('xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large');
    $fontWeight     = array('normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900', 'inherit');
    $s              = str_replace('font: ', '', $s);
    $array          = explode(' ', $s);
    $count          = count($array);
    $sizeFound      = false;
    $final          = array();
    $final['font-style']    = 'normal';
    $final['font-variant']  = 'normal';
    $final['font-weight']   = 'normal';
    for($i = 0; $i < $count; $i++){
        $cur = $array[$i];
        if($sizeFound){
            $final['font-family'] = isset($final['font-family']) ? $final['font-family'].$cur : $cur;
        }else if(strripos($cur,'%') !== false || strripos($cur,'px') !== false || in_array($cur, $fontSize)){
            $sizeFound = true;
            $size = explode('/', $cur);
            if(count($size) > 1){
                $final['font-size'] = $size[0];
                $final['line-height'] = $size[1];
            }else
                $final['font-size'] = $size[0];
        }else{ 
            if(in_array($cur, $fontStyle))
                $final['font-style'] = $cur;
            if(in_array($cur, $fontVariant))
                $final['font-variant'] = $cur;
            if(in_array($cur, $fontWeight))
                $final['font-weight'] = $cur;
        }   
    }
    $ret = '';
    foreach($final as $prop => $val)
        $ret .= $prop.': '.$val.';';
    return $ret;
}

我猜它可以优化。 :)

答案 3 :(得分:0)

您可以查看CSSTidy,其代码是开源的,并尝试对其进行反向工程。