<?php
/**
 * jsMath Plugin - see http://www.math.union.edu/~dpvc/jsmath/
 * 
 * Syntax:    <jsm> ...latex... </jsm>
 *         <jsmath> ...latex... </jsmath>
 * (optional)     $ ...latex... $
 * (optional)    \[ ...latex... \]
 * (optional)    \( ...latex... \)
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Holger <yllohy@gmail.com>
 * @author     Stephen Gould <sgould@cs.stanford.edu>
 **/

if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');

/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 **/
class syntax_plugin_jsmath extends DokuWiki_Syntax_Plugin {

  /**
   * Get an associative array with plugin info.
   **/
  function getInfo(){
    return array(
      'author' => 'Holger',
      'email'  => 'yllohy@gmail.com',
      'date'   => @file_get_contents(DOKU_PLUGIN.'jsmath/VERSION'),
      'name'   => 'jsMath Plugin',
      'desc'   => 'Plugin for displaying latex equations using MathJax or jsMath
      See http://www.mathjax.org
      See http://www.math.union.edu/~dpvc/jsmath/
      Syntax: <jsm(ath)?>math formulae</jsm(ath)?>',
        'url'    => 'http://www.dokuwiki.org/plugin:jsmath',
      );
  }

  function getType(){ return 'protected'; }
  function getAllowedTypes() {
    return array('disabled');
  }
  function getPType(){ return 'normal'; }
  function getSort(){ return 222; }

  /**
   * Connect pattern to lexer
   **/
  function connectTo($mode) {
    $this->Lexer->addEntryPattern('<jsm>(?=.*?</jsm>)',$mode,'plugin_jsmath');
    $this->Lexer->addEntryPattern('<jsmath>(?=.*?</jsmath>)',$mode,'plugin_jsmath');
    if($this->getConf('use_dollar'))
    {
      $this->Lexer->addEntryPattern('\$(?=.*?\$)',$mode,'plugin_jsmath');
    }
    if($this->getConf('use_rounded'))
    {
      $this->Lexer->addEntryPattern('\\\\\((?=.*?\\\\\))',$mode,'plugin_jsmath');
    }
    if($this->getConf('use_square'))
    {
      $this->Lexer->addEntryPattern('\\\\\[(?=.*?\\])',$mode,'plugin_jsmath');
    }
  }

  function postConnect() {
    $this->Lexer->addExitPattern('</jsm>','plugin_jsmath');
    $this->Lexer->addExitPattern('</jsmath>','plugin_jsmath');
    if($this->getConf('use_dollar'))
    {
      $this->Lexer->addExitPattern('\$','plugin_jsmath');
    }
    if($this->getConf('use_rounded'))
    {
      $this->Lexer->addExitPattern('\\\)','plugin_jsmath');
    }
    if($this->getConf('use_square'))
    {
      $this->Lexer->addExitPattern('\\\]','plugin_jsmath');
    }
  } 

  /**
   *      * Handler to prepare matched data for the rendering process.
   *           */
  function handle($match, $state, $pos, &$handler){
    switch ($state) {
    case DOKU_LEXER_ENTER : 
      if(preg_match("/^(\\\\\()$/", $match) > 0
       ||preg_match("/^(\\\$)$/", $match) > 0
       ||preg_match("/^(<jsm>)$/", $match) > 0)
      {
        return array($state, 'inline');
      }
      else
      {
        return array($state, 'block');
      }
      break;
    case DOKU_LEXER_MATCHED :
      break;
    case DOKU_LEXER_UNMATCHED :
      return array($state, $match);
      break;
    case DOKU_LEXER_EXIT :
      if(preg_match("/^(\\\\\))$/", $match) > 0
       ||preg_match("/^(\\\$)$/", $match) > 0
       ||preg_match("/^(<\/jsm>)$/", $match) > 0)
      {
        return array($state, 'inline');
      }
      else
      {
        return array($state, 'block');
      }
      break;
    case DOKU_LEXER_SPECIAL :
      break;
    }
    return array($state, '');
  }

  /**
   * Handle the actual output creation.
   **/
  function render($mode, &$renderer, $data) {
    $backend_is_jsmath = ($this->getConf('backend') != 'MathJax');
    if($mode == 'xhtml') {
      list($state, $match) = $data;
      switch ($state) {
      case DOKU_LEXER_ENTER :
        if ($match=='inline') {
          if($backend_is_jsmath)
          {
            $renderer->doc .= '<span class="math">';
          }
          else
          {
            $renderer->doc .= '<span dir="ltr"><script type="math/tex">';
          }
        } else {
          if($backend_is_jsmath)
          {
            $renderer->doc .= '<div class="math">';
          }
          else
          {
            $renderer->doc .= '<span dir="ltr"><script type="math/tex; mode=display">';
          }
        }
        break;
      case DOKU_LEXER_MATCHED :
        break;
      case DOKU_LEXER_UNMATCHED :
        if($backend_is_jsmath)
        {// jsMath needs < to be replaced with &lt; and so on.
          $renderer->doc .= $renderer->_xmlEntities($match);
        }
        else
        {
          $renderer->doc .= $match;
        }
        break;
      case DOKU_LEXER_EXIT :
        if ($match=='inline') {
          if($backend_is_jsmath)
          {
            $renderer->doc .= '</span>';
          }
          else
          {
            $renderer->doc .= '</script></span>';
          }
        } else {
          if($backend_is_jsmath)
          {
            $renderer->doc .= '</div>';
          }
          else
          {
            $renderer->doc .= '</script></span>';
          }
        }
        break;
      case DOKU_LEXER_SPECIAL :
        break;
      }
      return true;
    }
    return false;
  }
}

//Setup VIM: ex: et ts=4 enc=utf-8 :
