Kaynağa Gözat

Merge pull request #2198 from visuddhinanda/laravel

添加逐段对读支持
visuddhinanda 1 yıl önce
ebeveyn
işleme
6850b99f07

+ 32 - 4
app/Console/Commands/TestMdRender.php

@@ -117,6 +117,31 @@ class TestMdRender extends Command
         title=第一章 戒律概说(Vinaya)|
         style=modal}}
         md;
+
+        $data['footnote'] = <<<md
+        # title
+        content `note content` `note2 content`
+        md;
+
+        $data['paragraph'] = <<<md
+        # title
+        content
+
+        {{168-916-10-37}}
+        {{168-916-10-37}}
+
+        the end
+        md;
+
+        $data['img'] = <<<md
+        # title
+        content
+
+        ![aaa](/images/aaa.jpg)
+
+        the end
+        md;
+
         $data['empty'] = '';
 
         Markdown::driver($this->option('driver'));
@@ -134,10 +159,13 @@ class TestMdRender extends Command
                 if(!empty($_item) && $key !==$_item){
                     continue;
                 }
-                echo MdRender::render($value,
-                                    ['00ae2c48-c204-4082-ae79-79ba2740d506'],
-                                    null,'read','translation',
-                                    $contentType="markdown",$format);
+                $mdRender = new MdRender([
+                    'format'=>$format,
+                    'footnote'=>true,
+                    'paragraph'=>true,
+                ]);
+                $output = $mdRender->convert($value,['00ae2c48-c204-4082-ae79-79ba2740d506']);
+                echo $output;
             }
         }
         return 0;

+ 53 - 14
app/Http/Api/MdRender.php

@@ -28,6 +28,8 @@ class MdRender{
         'debug'=>[],
         'studioId'=>null,
         'lang'=>'zh-Hans',
+        'footnote'=>false,
+        'paragraph'=>false,
         ];
 
     public function __construct($options=[])
@@ -37,6 +39,31 @@ class MdRender{
         }
     }
 
+    /**
+     * 将句子模版组成的段落复制一份,为了实现巴汉逐段对读
+     */
+    private function preprocessingForParagraph($input){
+        if(!$this->options['paragraph']){
+            return $input;
+        }
+        $paragraphs = explode("\n\n",$input);
+        $output = [];
+        foreach ($paragraphs as $key => $paragraph) {
+            # 判断是否是纯粹的句子模版
+            $pattern = "/\{\{sent\|id=([0-9].+?)\}\}/";
+            $replacement = '';
+            $space = preg_replace($pattern,$replacement,$paragraph);
+            if(empty(trim($space))){
+                $output[] = str_replace('}}','|text=origin}}',$paragraph);
+                $output[] = str_replace('}}','|text=translation}}',$paragraph);
+            }else{
+                $output[] = $paragraph;
+            }
+        }
+
+        return implode("\n\n",$output);
+    }
+
     /**
      * 按照{{}}把字符串切分成三个部分。模版之前的,模版,和模版之后的
      */
@@ -99,7 +126,7 @@ class MdRender{
 
     private function wiki2xml(string $wiki,$channelId=[]):string{
         /**
-         * 把模版转换为xml
+         * 渲染markdown里面的模版
          */
         $remain = $wiki;
         $buffer = array();
@@ -216,9 +243,8 @@ class MdRender{
             Log::error($xml);
             return "<span>xml解析错误</span>";
         }
-         */
+        */
 
-        //$tpl_list = $dom->xpath('//MdTpl');
         $tpl_list = $doc->getElementsByTagName('dfn');
 
         foreach ($tpl_list as $key => $tpl) {
@@ -315,8 +341,7 @@ class MdRender{
                     return '';
                 }
                 break;
-            case 'text':
-            case 'simple':
+            case 'tex':
                 if(isset($tplProps)){
                     if(is_array($tplProps)){
                         return '';
@@ -328,7 +353,7 @@ class MdRender{
                     return '';
                 }
                 break;
-            case 'tex':
+            default: /**text simple markdown */
                 if(isset($tplProps)){
                     if(is_array($tplProps)){
                         return '';
@@ -340,13 +365,12 @@ class MdRender{
                     return '';
                 }
                 break;
-            default:
-                return '';
-                break;
         }
     }
 
-
+    /**
+     * 将markdown文件中的模版转换为标准的wiki模版
+     */
     private function markdown2wiki(string $markdown): string{
         //$markdown = mb_convert_encoding($markdown,'UTF-8','UTF-8');
         $markdown = iconv('UTF-8','UTF-8//IGNORE',$markdown);
@@ -447,7 +471,7 @@ class MdRender{
 
         #替换句子模版
         $pattern = "/\{\{([0-9].+?)\}\}/";
-        $replacement = '{{sent|$1}}';
+        $replacement = '{{sent|id=$1}}';
         $markdown = preg_replace($pattern,$replacement,$markdown);
 
         /**
@@ -570,11 +594,12 @@ class MdRender{
             }
         }
         $wiki = $this->markdown2wiki($markdown);
-        $html = $this->wiki2xml($wiki,$channelId);
+        $wiki = $this->preprocessingForParagraph($wiki);
+        $markdownWithTpl = $this->wiki2xml($wiki,$channelId);
         if(!is_null($queryId)){
-            $html = $this->xmlQueryId($html, $queryId);
+            $html = $this->xmlQueryId($markdownWithTpl, $queryId);
         }
-        $html = $this->markdownToHtml($html);
+        $html = $this->markdownToHtml($markdownWithTpl);
 
         //后期处理
         $output = '';
@@ -605,6 +630,20 @@ class MdRender{
                 break;
             case 'html':
                 $output = htmlspecialchars_decode($html,ENT_QUOTES);
+                //处理脚注
+                if($this->options['footnote'] && isset($GLOBALS['note']) && count($GLOBALS['note'])>0){
+                    $output .= '<div><h1>endnote</h1>';
+                    foreach ($GLOBALS['note'] as $footnote) {
+                        $output .= '<p><a name="footnote-'.$footnote['sn'].'">['.$footnote['sn'].']</a> '.$footnote['content'].'</p>';
+                    }
+                    $output .= '</div>';
+                    unset($GLOBALS['note']);
+                }
+                //处理图片链接
+                $output = str_replace('<img src="','<img src="'.config('app.url'),$output);
+                break;
+            case 'markdown':
+                $output = $markdownWithTpl;
                 break;
         }
         return $output;

+ 88 - 20
app/Http/Api/TemplateRender.php

@@ -35,7 +35,7 @@ class TemplateRender{
      * string $format  'react' | 'text' | 'tex' | 'unity'
      * @return void
      */
-    public function __construct($param, $channelInfo, $mode,$format='react',$studioId,$debug=[],$lang='zh-Hans')
+    public function __construct($param, $channelInfo, $mode,$format='react',$studioId='',$debug=[],$lang='zh-Hans')
     {
         $this->param = $param;
         foreach ($channelInfo as $value) {
@@ -337,6 +337,19 @@ class TemplateRender{
                     $output = $props["word"];
                 }
                 break;
+            case 'markdown':
+                if(isset($props["meaning"])){
+                    $key = 'term-'.$props["word"];
+                    if(isset($GLOBALS[$key])){
+                        $output = $props["meaning"];
+                    }else{
+                        $GLOBALS[$key] = 1;
+                        $output = $props["meaning"].'('.$props["word"].')';
+                    }
+                }else{
+                    $output = $props["word"];
+                }
+                break;
             default:
                 if(isset($props["meaning"])){
                     $output = $props["meaning"];
@@ -391,7 +404,7 @@ class TemplateRender{
                     $GLOBALS['note'] = array();
                 }
                 $GLOBALS['note'][] = [
-                        'sn' => 1,
+                        'sn' => $GLOBALS['note_sn'],
                         'trigger' => $trigger,
                         'content' => MdRender::render($props["note"],
                                         $this->channel_id,
@@ -419,6 +432,23 @@ class TemplateRender{
             case 'simple':
                 $output = '';
                 break;
+            case 'markdown':
+                if(isset($GLOBALS['note_sn'])){
+                    $GLOBALS['note_sn']++;
+                }else{
+                    $GLOBALS['note_sn'] = 1;
+                }
+                $content = MdRender::render(
+                            $props["note"],
+                            $this->channel_id,
+                            null,
+                            'read',
+                            'translation',
+                            'markdown',
+                            'markdown'
+                        );
+                $output = '<footnote id="'.$GLOBALS['note_sn'].'">'.$content.'</footnote>';
+                break;
             default:
                 $output = '';
                 break;
@@ -821,8 +851,10 @@ class TemplateRender{
     }
     private  function render_sent(){
 
-        $sid = $this->get_param($this->param,"sid",1);
+        $sid = $this->get_param($this->param,"id",1);
         $channel = $this->get_param($this->param,"channel",2);
+        $text = $this->get_param($this->param,"text",2,'both');
+
         if(!empty($channel)){
             $channels = explode(',',$channel);
         }else{
@@ -863,6 +895,11 @@ class TemplateRender{
                 break;
             case 'text':
                 $output = '';
+                if(isset($props['origin']) && is_array($props['origin'])){
+                    foreach ($props['origin'] as $key => $value) {
+                        $output .= $value['html'];
+                    }
+                }
                 if(isset($props['translation']) && is_array($props['translation'])){
                     foreach ($props['translation'] as $key => $value) {
                         $output .= $value['html'];
@@ -871,11 +908,23 @@ class TemplateRender{
                 break;
             case 'html':
                 $output = '';
-                if(isset($props['translation']) && is_array($props['translation'])){
-                    foreach ($props['translation'] as $key => $value) {
-                        $output .= '<span class="sentence">'.$value['html'].'</span>';
+                $output .= '<span class="sentence">';
+                if($text === 'both' || $text === 'origin'){
+                    if(isset($props['origin']) && is_array($props['origin'])){
+                        foreach ($props['origin'] as $key => $value) {
+                            $output .= '<span class="origin">'.$value['html'].'</span>';
+                        }
                     }
                 }
+                if($text === 'both' || $text === 'translation'){
+                    if(isset($props['translation']) && is_array($props['translation'])){
+                        foreach ($props['translation'] as $key => $value) {
+                            $output .= '<span class="translation">'.$value['html'].'</span>';
+                        }
+                    }
+                }
+
+                $output .= '</span>';
                 break;
             case 'tex':
                 $output = '';
@@ -887,27 +936,46 @@ class TemplateRender{
                 break;
             case 'simple':
                 $output = '';
-                if(isset($props['translation']) &&
-                   is_array($props['translation']) &&
-                   count($props['translation']) > 0
-                   ){
-                    $sentences = $props['translation'];
-                    foreach ($sentences as $key => $value) {
-                        $output .= $value['html'];
+                if($text === 'both' || $text === 'origin'){
+                    if(empty($output)){
+                        if(isset($props['origin']) &&
+                                is_array($props['origin']) &&
+                                count($props['origin']) > 0
+                                ){
+                            foreach ($props['origin'] as $key => $value) {
+                                $output .= $value['html'];
+                            }
+                        }
                     }
                 }
-                if(empty($output)){
-                    if(isset($props['origin']) &&
-                            is_array($props['origin']) &&
-                            count($props['origin']) > 0
-                            ){
-                        $sentences = $props['origin'];
-                        foreach ($sentences as $key => $value) {
+                if($text === 'both' || $text === 'translation'){
+                    if(isset($props['translation']) &&
+                    is_array($props['translation']) &&
+                    count($props['translation']) > 0
+                    ){
+                        foreach ($props['translation'] as $key => $value) {
                             $output .= $value['html'];
                         }
                     }
                 }
                 break;
+            case 'markdown':
+                $output = '';
+                if($text === 'both' || $text === 'origin'){
+                    if(isset($props['origin']) && is_array($props['origin'])){
+                        foreach ($props['origin'] as $key => $value) {
+                            $output .= "\n\n". $value['html'];
+                        }
+                    }
+                }
+                if($text === 'both' || $text === 'translation'){
+                    if(isset($props['translation']) && is_array($props['translation'])){
+                        foreach ($props['translation'] as $key => $value) {
+                            $output .= "\n\n". $value['html'];
+                        }
+                    }
+                }
+                break;
             default:
                 $output = '';
                 break;