<?php if (!defined('PmWiki')) exit();
/*  Copyright 2016 Christopher J. Cox (chriscox@endlessnow.com)
    This file is pmpygment.php; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
    by the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.  

    Requires python and pygment on your server.

    This is a simple markup wrapper to display code highlighting using
    pygmentize.

    (:sourcecode lang="html" linenos=true linenostart=100  hl_lines="5"  style=manni:)
    <!--This is a comment. Comments are not displayed in the browser-->
    <table align=center style="background: ivory;color:maroon;font-style:italic;font-family:arial;font-weight:bold;font-size:10pt;">
    <tr><th> Heading 1 </th><th> Heading 2 </th></tr>
    <tr>
    <td style="padding:10px;"> This is cell 1 text </td>
    <td style="padding:10px;"> This is cell 2 text </td>
    </tr>
    </table>
    (:sourcecodeend:)

*/

$RecipeInfo['PmPygment']['Version'] = '2018-03-22';

Markup(
  'pmpygment',
  'fulltext',
  '/\\(:sourcecode[ 	]*(.*?):\\)(.*?)\\(:sourcecodeend:\\)/si',
  "PmPygment");


function PmPygment($m) {
  global $PubCacheDir, $UploadFileFmt, $UploadUrlFmt, $EnableDirectDownload,
    $HTMLStylesFmt;

  extract($GLOBALS['MarkupToHTML']);
  @list($m0, $options, $sourceblock) = $m;
  
  $version = '1.2';
  $defaults = array(
    'lang' => '',
    'title' => '',
    'style' => '',
    'linenos' => 'false',
    'linenostart' => 1,
    'hl_lines' => '',
    'height' => '100%',
    'iframe' => 'false',
    'noclasses' => 'true',
  );
  $opt = array_merge($defaults, ParseArgs($options));

  if ($opt['lang'] == '') {
    $out='<pre>Source: Option lang=&lt;language&gt; required</pre>';
    return Keep($out);
  }

  $checkmd5 = md5("$version"."$options"."$sourceblock");
  // this recipe could be extended to handle files that already exist.
  $inlinefile = rawurlencode("pmpygment-".$checkmd5.'.html');
  $upname = MakeUploadName($pagename, $inlinefile);
  $dirpath = FmtPageName("$UploadFileFmt", $pagename);
  $filepath = FmtPageName("$UploadFileFmt/$upname", $pagename);

  SDV($PubCacheDir, "pub/cache");
  SDV($PmPygmentPgm, "/usr/bin/pygmentize");
  SDV($PmPygmentCacheDir, "$PubCacheDir");
  SDV($PmPygmentIFrameDefaultStyle, '#wikitext .pmpygmentframe {  width: 100%; border: none; }');
  
  $HTMLStylesFmt['pmpygmentframe'] = "$PmPygmentIFrameDefaultStyle";
  $HTMLStylesFmt['highlighttable'] = '.highlighttable { width: 100%; }';
  if (!file_exists($filepath)) {
    if (!file_exists($dirpath)) {
      mkdir($dirpath,$mode=0755,$recursive=true);
    }

    $cmd="$PmPygmentPgm -f html";

    // Add lang
    $cmd=$cmd . ' ' . '-l ' . $opt['lang'];
    
    // Get the ball rolling on opts
    $pygmentopts = "-O linenostart=" . $opt['linenostart'];

    if ($opt['iframe'] == 'true') {
       $pygmentopts = $pygmentopts . ",full";
       $opt['noclasses'] = 'false';
    }
    if ($opt['noclasses'] == 'true') {
       $pygmentopts = $pygmentopts . ",noclasses";
    }
    if ($opt['style'] != '') {
       $pygmentopts = $pygmentopts . ",style=".$opt['style'];
    }
    if ($opt['linenos'] != 'false') {
       $pygmentopts = $pygmentopts . ",linenos=".$opt['linenos'];
    }
    if ($opt['hl_lines'] != '') {
       $pygmentopts = $pygmentopts . ",hl_lines='" . $opt['hl_lines'] . "'";
    }
    if ($opt['title'] != '') {
       $pygmentopts = $pygmentopts . ",title='" . $opt['title'] . "'";
    }
    // Add pygment options
    $cmd=$cmd . ' ' . $pygmentopts;

    // finally add outfile
    $cmd=$cmd . ' -o ' . $filepath;

    // Call pygmentize
    $pygment_descriptors = array(
      0 => array('pipe', 'r'),
      1 => array('pipe', 'w'),
      2 => array('pipe', 'w')
    );
    $pygment_proc = proc_open($cmd, $pygment_descriptors, $pipes);
    if (is_resource($pygment_proc)) {
      stream_set_blocking($pipes[0], 0);
      stream_set_blocking($pipes[1], 0);
      stream_set_blocking($pipes[2], 0);
      fwrite($pipes[0], html_entity_decode($sourceblock));
      fclose($pipes[0]);
      $std_out=stream_get_contents($pipes[1]);
      fclose($pipes[1]);
      $err_out=stream_get_contents($pipes[2]);
      fclose($pipes[2]);
      $pygment_proc_rc = proc_close($pygment_proc);
      if ($pygment_proc_rc) {
        unlink($filepath);
        // Not sure what happens to std_out and err_out when it errors... they
        //  always seem empty.
        $out="<pre>pygmentize has errored. $err_out\n$std_out</pre>";
        //$out="<pre>pygmentize has errored. " . implode(" ", $output) . "</pre>";
        //$out="<pre>pygmentize has errored." . $std_out . "\n" . $err_out . "</pre>";
      }
    } 
  }
  if (file_exists($filepath)) {
    $uploadpath = PUE(FmtPageName(IsEnabled($EnableDirectDownload, 1)
      ? "$UploadUrlFmt$UploadPrefixFmt/$upname"
      : "{\$PageUrl}?action=download&upname=$upname", $pagename));
    if ($opts['iframe'] == 'true') {
      $out='<iframe class="pmpygmentiframe" height="'.$opt['height'].'" src="'.$uploadpath.'"></iframe>';
    } else {
      $out=file_get_contents($uploadpath);
    }
    return Keep($out);
  } else {
    return Keep($out);
  }
}