file = $filename; //设置当前文件 $this->mdGen = $this->content($filename); //获取生成器 $this->flag = 'idel'; //闲置 $this->lines = array(); //所有行状态 $this->line_count = 0; //行数归0 } private function content($file){ //获取生成器 if(file_exists($file)){ $fh = fopen($file,"r"); while(!feof($fh)){ yield fgets($fh); } fclose($fh); }else{ return null; } } //遍历每一个字符 private function every($str){ $l = strlen($str); for($i=0;$i<$l;$i++) if(ord($str[$i])<0x80) yield $str[$i]; else{ yield $str[$i].$str[$i+1].$str[$i+2]; //三个字节 $i+=2; } } //解析 private function parse(){ $ctnt = $this->mdGen; //生成器 $ret=array(); if($ctnt != null){ $ret = array(); foreach($ctnt as $line){ if($this->flag != 'code') $line=ltrim($line); //删除左边 if(strlen($line)){ $ch = $line[0]; //判断第一个字符 $type=ctype_punct($ch);//标点符号 if($this->flag !== 'code') $line=preg_replace('/\s{2,}$/','
',$line); //非代码模式 $ret[] = $this->parseLine($line,$type); //解析行 }else{ //空行 switch($this->flag){ case 'ul': case 'ol': $ret[]="flag>"; $this->flag_pre = $this->flag; $this->flag = 'idel'; break; case 'table': $this->flag = 'idel'; $ret[]=''; break; default: if($this->flag != 'el') $ret[] = '
'; $this->flag = 'el'; //空行 } } } } $this->lines = $ret; return $ret; } //生成blockquote private function genQuote($level,$content){ if($level<=0) return ""; return str_repeat('
',$level).$content.str_repeat('
',$level); } //检查是否处于某个状态,默认检查是否处于代码状态 private function check($value='code'){ return ($this->flag == $value); } /** * 生成一行新的表格列 * $data:需要输入的数据 * $type:生成类型 * $wrap:最快层包裹 * $sep:分隔符 */ private function genRow($data,$type='td',$wrap='tr',$sep='|'){ $ret=''; $mat = explode($sep,$data); foreach($mat as $elem) $ret.="<$type>".$elem.""; return "<$wrap>".$ret.""; } /** * 解析行内元素 * bold,italic,code,link,pic */ private function parseInner($str){ $str=preg_replace('/\*\*\*([^\*\n\r]+)\*\*\*/','\1',$str); //加粗并加斜字体 $str=preg_replace('/\*\*([^\*\n\r]+)\*\*/','\1',$str); //加粗字体 $str=preg_replace('/\*([^\*\n\r]+)\*/','\1',$str); //斜体 $str=preg_replace('/```([^`\n\r]+)```/','\1',$str); //代码 $str=preg_replace('/`([^`\n\r]+)`/','\1',$str); //代码 $str=preg_replace('/!\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','\1',$str); //图片 $str=preg_replace('/\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','\1',$str); //图片 return $str; } /** * 按照给定规则解析字符串: * type: * true 符号 * false 文字 * 返回: * array('type'=>类型,'parts'=>array(...)) */ private function parseLine($str,$type){ if(strlen($str) == 0){ return array('type'=>'p','parts'=>[]); //返回空段 } $valid_str = rtrim($str); //去除右边的空格 $str = $valid_str; $output = ''; //需要输出的字符串 if($type == true){ //标点 $type_str = ''; //类型字符串 $data_str = ''; $flag = 0; foreach($this->every($str) as $ch){ if(!ctype_punct($ch)){ $flag = 1; } if($flag == 0) $type_str .= $ch; else $data_str .= $ch; } switch($type_str){ case '#': $wrap = 'h1'; $this->flag_like = 'h1'; break; case '##': $wrap = 'h2'; $this->flag_like = 'h2'; break; case '###': $wrap = 'h3'; $this->flag_like = 'h3'; break; case '####': $wrap = 'h4'; $this->flag_like = 'h4'; break; case '#####': $wrap = 'h5'; $this->flag_like = 'h5'; break; case '######': $wrap = 'h6'; $this->flag_like = 'h6'; break; case '+': case '-': $wrap = 'li'; $this->flag_like = 'ul'; if($this->flag != 'code'){ if($this->flag != 'ul'){ $this->flag_pre = $this->flag; $this->flag = 'ul'; $output.='