方針

  • インラインプラグインの引数が長くなると改行が必要になる。
    • 特に TeX を利用している eq とか。
  • 複数行ブロックプラグインを真似て同じ構文で複数行インラインプラグインを導入。
  • 引数展開もブロックプラグインに準じて非展開。
    • 技術上、従来のインラインプラグインのように引数を展開するのは困難。
    • TeX などの場合、引数非展開の方が好都合。

仕様

$plugin (arg ){{
body
}}

で、

&plugin (arg,body )

と同等の振る舞い。

  • 引数の処理は複数行ブロックプラグインに準ずる。
    • argbody は引数非展開。
    • body の前、各行末は "\r" を挿入。

実装

  • lib/convert_html.php にて、function & Factory_Div をコピーし、function & Factory_Span に改造。
    • !」の行は function Factory_Div からの差分。
      • # の正規表現を \$ に、new Divnew Span に置換。
  •   1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
    
    !function & Factory_Span(& $root, $text)
     {
         $matches = array();
         
         // Seems block plugin?
         if (PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK) {
             // Usual code
    !        if (preg_match('/^\$([^\(]+)(?:\((.*)\))?/', $text, $matches) &&
                 exist_plugin_convert($matches[1])) {
    !            return new Inline($matches);
             }
         } else {
             // Hack code
    !        if(preg_match('/^\$([^\(\{]+)(?:\(([^\r]*)\))?(\{*)/', $text, $matches) && 
                 exist_plugin_inline($matches[1])) {
                 $len  = strlen($matches[3]);
                 $body = array();
                 if ($len == 0) {
                     return new Span($matches); // Seems legacy block plugin
                 } else if (preg_match('/\{{' . $len . '}\s*\r(.*)\s*\}{' . $len . '}/', $text, $body)) { 
                     $matches[2] .= $body[1];
                     return new Span($matches); // Seems multiline-enabled block plugin
                 }
             }
         }
         return new Inline($text);
     }
    
  • 同ファイルの class Div をコピーし、class Span に改造。
    • !」の行は class Div からの差分。
    • +」の行は class Inline からのコピー。
      • これらは、インラインプラグインで始まる文を、後に段落に昇格させるための関数。
  •   1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
    
    !// $something (started with '$') for Multiline-enabled Argment-keeping Inline-plugin
    !class Span extends Element
     {
         var $name;
         var $param;
         
    !    function Span($out)
         {
             parent::Element();
             list(, $this->name, $this->param) = array_pad($out, 3, '');
         }
         
         function canContain(& $obj)
         {
             return FALSE;
         }
         
    +    function & insert(& $obj)
    +    {
    +        $this->elements[] = $obj->elements[0];
    +        return $this;
    +    }
         
         function toString()
         {
             // Call $plugin
    !        return do_plugin_inline($this->name, $this->param);
         }
         
    +    function & toPara($class = '')
    +    {
    +        $obj = & new Paragraph('', $class);
    +        $obj->insert($this);
    +        return $obj;
    +    }
     }
    
  • 同ファイル、class Bodyvar $factoriesに対し、
  •   1
      2
      3
      4
      5
      6
      7
    
         var $factories = array(
             ':' => 'DList',
             '|' => 'Table',
             ',' => 'YTable',
    -        '#' => 'Div');
    +        '#' => 'Div',
    +        '$' => 'Span');
    
  • 同クラス class Bodyfunction parseの複数行ブロックプラグインの分岐をコピーして改造。
    • !」はコピー元に対する変更。
    • 丸引数の有無をチェックし、波引数との間の「,」の有無を調節。
  •   1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
    
    !            // Multiline-enabled Argment-keeping Inline-plugin
                 if (! PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK &&
    !                preg_match('/^\$[^({]*(\((.*)\))?(\{\{+)\s*$/', $line, $matches)) {
                     $delimiter = "\r";
    !                $len = strlen($matches[3]);
    !                $line .= ($matches[2] == '') ? $delimiter : ','.$delimiter;
                     while (! empty($lines)) {
                         $next_line = rtrim(array_shift($lines), "\r\n");
                         if ($indent_format)
                         {
                             preg_match('/^(\s{'.$indent.'}?)?(.*)$/', $next_line, $matches);
                             $next_line = $matches[2];
                         }
                         
                         if (preg_match('/\s*\}{' . $len . '}/', $next_line)) {
                             $line .= ltrim($next_line);
                             break;
                         } else {
                             $line .= $next_line . $delimiter;
                         }
                     }
                 }
    
  • 複数行インラインプラグインをインライン要素と同じ振る舞いさせるため、~同ファイル中の「is_a($obj, 'Inline')」を「is_a($obj, 'Inline') || is_a($obj, 'Span')」に置換。
    • ただし、class Inlinefunction canContain だけは変えてはダメ。(理由は説明できないが、経験則)
    • 同ファイル、class Paragraphclass Align のそれぞれの function canContain にて、
    •   1
        2
        3
        4
        5
      
           function canContain($obj)
           {
      -        return is_a($obj, 'Inline');
      +        return is_a($obj, 'Inline') || is_a($obj, 'Span');
           }
      
    • 同クラス class Bodyfunction & insertにて、
    •   1
        2
        3
        4
        5
        6
      
          function & insert(& $obj)
          {
      -       if (is_a($obj, 'Inline')) $obj = & $obj->toPara();
      +       if (is_a($obj, 'Inline') || is_a($obj, 'Span')) $obj = & $obj->toPara();
              return parent::insert($obj);
          }
      
    • 同ファイル、class BQuotefunction & insert にて、
    •   1
        2
        3
        4
        5
        6
      
          function & insert(& $obj)
          {
              // BugTrack/521, BugTrack/545
      -       if (is_a($obj, 'inline'))
      +       if (is_a($obj, 'inline') || is_a($obj, 'Span'))
                  return parent::insert($obj->toPara(' class="quotation"'));
      

課題

  • プラグインの書式
    • 第1案:先頭1字で書式決定
      • 既存の「#」と「&」の間を日本語キーボード配列順(=ASCII順)に補間。
    •  引数非展開引数展開
      ブロックインラインブロックインライン
      単一行#〜(〜){〜}; $〜(〜){〜}; %〜(〜){〜}; &〜(〜{〜};
      複数行#〜(〜){{

      }}
      $〜(〜){{

      }}
      %〜(〜){{

      }}
      &〜(〜){{

      }}
    • 第2案:先頭1字でブロック/インラインを決定、第2字で引数展開/非展開を決定。
      • 既存の「#」と「&」のみで解決。
      • #」と「&」はそれぞれ「##」と「&&」の省略的扱い。
    •  ブロックインライン
      引数非展開引数展開引数非展開引数展開
      単一行##〜(〜){〜};#&〜(〜){〜};&#〜(〜){〜};&&〜(〜{〜};
      複数行##〜(〜){{

      }}
      #&〜(〜){{

      }}
      &#〜(〜){{

      }}
      &&〜(〜){{

      }}
リロード   新規 編集 解凍 差分 添付 複製 改名   初基 一覧 検索 最新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: 2012.0229 (水) 0806.0200 (4438d)