Browse Source

用xml 实现模版渲染

visuddhinanda 3 years ago
parent
commit
93e01f010d
1 changed files with 168 additions and 9 deletions
  1. 168 9
      app/Http/Api/MdRender.php

+ 168 - 9
app/Http/Api/MdRender.php

@@ -10,18 +10,150 @@ use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Log;
 
 class MdRender{
-    /**
-     *
-     */
-    public static function render($markdown,$channelId,$isArticle=false){
+    public static function wiki2xml(string $wiki):string{
+        /**
+         * 替换{{}} 到xml之前 要先把换行符号去掉
+         */
+        $html = str_replace("\n","",$wiki);
+
+        $pattern = "/\{\{(.+?)\|/";
+        $replacement = '<MdTpl name="$1"><param>';
+        $html = preg_replace($pattern,$replacement,$html);
+        $html = str_replace("}}","</param></MdTpl>",$html);
+        $html = str_replace("|","</param><param>",$html);
+
+        /**
+         * 替换变量名
+         */
+
+        $pattern = "/<param>([a-z]+?)=/";
+        $replacement = '<param name="$1">';
+        $html = preg_replace($pattern,$replacement,$html);
+
+        $html = str_replace("<p>","<div>",$html);
+        $html = str_replace("</p>","</div>",$html);
+        $html = "<xml>".$html."</xml>";
+        return $html;
+    }
+    public static function xmlQueryId(string $xml, string $id):string{
+        $dom = simplexml_load_string($xml);
+        $tpl_list = $dom->xpath('//MdTpl');
+        foreach ($tpl_list as $key => $tpl) {
+            foreach ($tpl->children() as  $param) {
+                # 处理每个参数
+                if($param->getName() === "param"){
+                    foreach($param->attributes() as $pa => $pa_value){
+                        $pValue = $pa_value->__toString();
+                        if($pa === "name" && $pValue === "id"){
+                            if($param->__toString() === $id){
+                                return $tpl->asXML();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return "<div></div>";
+    }
+    public static function take_sentence(string $xml):array{
+        $output = [];
+        $dom = simplexml_load_string($xml);
+        $tpl_list = $dom->xpath('//MdTpl');
+        foreach ($tpl_list as $key => $tpl) {
+            foreach($tpl->attributes() as $a => $a_value){
+                if($a==="name"){
+                    if($a_value->__toString() ==="sent"){
+                        foreach ($tpl->children() as  $param) {
+                            # 处理每个参数
+                            if($param->getName() === "param"){
+                                $sent = $param->__toString();
+                                if(!empty($sent)){
+                                    $output[] = $sent;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return $output;
+    }
+    public static function xml2tpl(string $xml, $channelId=""):string{
+        /**
+         * 解析xml
+         * 获取模版参数
+         * 生成react 组件参数
+         */
+        $dom = simplexml_load_string($xml);
+        $tpl_list = $dom->xpath('//MdTpl');
+        foreach ($tpl_list as $key => $tpl) {
+            /**
+             * 遍历 MdTpl 处理参数
+             */
+            $props = [];
+            $tpl_name = '';
+            foreach($tpl->attributes() as $a => $a_value){
+                if($a==="name"){
+                    $tpl_name = $a_value;
+                }
+            }
+            $param_id = 0;
+            foreach ($tpl->children() as  $param) {
+                # 处理每个参数
+                if($param->getName() === "param"){
+                    $param_id++;
+                    $props["{$param_id}"] = $param->__toString();
+                    foreach($param->attributes() as $pa => $pa_value){
+                        if($pa === "name"){
+                            $props["{$pa_value}"] = $param->__toString();
+                        }
+                    }
+                }
+            }
+            /**
+             * 生成模版参数
+             */
+            $tplRender = new TemplateRender($props,$channelId,'edit');
+            $tplProps = $tplRender->render($tpl_name);
+            if($tplProps){
+                $tpl->addAttribute("props",$tplProps['props']);
+                $tpl->addAttribute("tpl",$tplProps['tpl']);
+                $tpl->addChild($tplProps['tag'],$tplProps['html']);
+            }
+        }
+        $html = str_replace('<?xml version="1.0"?>','',$dom->asXML()) ;
+        $html = str_replace(['<xml>','</xml>'],['<span>','</span>'],$html);
+        return $html;
+    }
 
+    public static function render2($markdown,$channelId='',$queryId=null){
+        $wiki = MdRender::markdown2wiki($markdown);
+        $html = MdRender::wiki2xml($wiki);
+        if(!is_null($queryId)){
+            $html = MdRender::xmlQueryId($html, $queryId);
+        }
+        $tpl = MdRender::xml2tpl($html,$channelId);
+        return $tpl;
+    }
+    public static function markdown2wiki(string $markdown): string{
+        /**
+         * 替换换行符
+         * react 无法处理 <br> 替换为<div></div>代替换行符作用
+         */
+        $markdown = str_replace('<br>','<div></div>',$markdown);
+
+        /**
+         * markdown -> html
+         */
         $html = Str::markdown($markdown);
+
         #替换术语
         $pattern = "/\[\[(.+?)\]\]/";
         $replacement = '{{term|$1}}';
         $html = preg_replace($pattern,$replacement,$html);
 
-        #替换句子
+        #替换句子模版
         $pattern = "/\{\{([0-9].+?)\}\}/";
         $replacement = '{{sent|$1}}';
         $html = preg_replace($pattern,$replacement,$html);
@@ -29,14 +161,31 @@ class MdRender{
         #替换注释
         #<code>bla</code>
         #{{note:bla}}
-        #替换术语
         $pattern = '/<code>(.+?)<\/code>/';
         $replacement = '{{note|$1}}';
         $html = preg_replace($pattern,$replacement,$html);
+        return $html;
+    }
+
+    /**
+     *
+     */
+    public static function render($markdown,$channelId,$queryId=null){
+        return MdRender::render2($markdown,$channelId,$queryId);
+
+        $html = MdRender::markdown2wiki($markdown);
 
+        /**
+         * 转换为Mustache模版
+         */
         $pattern = "/\{\{(.+?)\}\}/";
         $replacement = "\n{{#function}}\n$1\n{{/function}}\n";
         $html = preg_replace($pattern,$replacement,$html);
+
+        /**
+         * Mustache_Engine 处理Mustache模版
+         * 把Mustache模版内容转换为react组件
+         */
         $m = new \Mustache_Engine(array('entity_flags' => ENT_QUOTES));
         $html = $m->render($html, array(
           'function' => function($text) use($m,$channelId) {
@@ -81,9 +230,18 @@ class MdRender{
                 case 'sent':
                     $tplName = "sentedit";
                     $innerString = "";
-                    $sentId = trim($param[1]);
+                    $sentInfo = explode('@',trim($param[1]));
+                    $sentId = $sentInfo[0];
                     $Sent = new CorpusController();
-                    $html = $Sent->getSentTpl($param[1],[$channelId]);
+                    if(empty($channelId)){
+                        $channels = [];
+                    }else{
+                        $channels = [$channelId];
+                    }
+                    if(isset($sentInfo[1])){
+                        $channels = [$sentInfo[1]];
+                    }
+                    $html = $Sent->getSentTpl($param[1],$channels);
                     return $html;
                     break;
                 case 'quote':
@@ -148,6 +306,7 @@ class MdRender{
             $html = \str_replace(['<p>','</p>'],'',$html);
         }
         //LOG::info($html);
-        return $html;
+        return "<xml>{$html}</xml>";
     }
+
 }