<?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'] = '2025-01-19';

SDV($PmPygmentPgm, '/usr/bin/pygmentize');
SDV($PmPygmentCacheDir, "$PubCacheDir");
SDV($PmPygmentSecureAttachments, 0);
SDV($HTMLStylesFmt['pmpygmentframe'], '#wikitext .pmpygmentframe {	width: 100%; border: none; }');
SDV($HTMLStylesFmt['pmpygmenthighlighttable'], '.highlighttable { width: 100%; }');

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

function PmPygment($m) {
	$options = $m[1];
	$sourceblock = preg_replace('/<:vspace>/', '', $m[2]);

	global $PubCacheDir, $UploadFileFmt, $UploadUrlFmt, $EnableDirectDownload,
		$HTMLStylesFmt, $pagename, $RecipeInfo;
	global $PmPygmentPgm, $PmPygmentCacheDir, $PmPygmentSecureAttachments;

	$version = $RecipeInfo['PmPygment']['Version'];
	$defaults = [
		'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);

	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 .= ",full";
			 $opt['noclasses'] = 'false';
		}
		if ($opt['noclasses'] == 'true') {
			 $pygmentopts .= ",noclasses";
		}
		if ($opt['style'] != '') {
			 $pygmentopts .= ",style={$opt['style']}";
		}
		if ($opt['linenos'] != 'false') {
			 $pygmentopts .= ",linenos";
		}
		if ($opt['hl_lines'] != '') {
			 $pygmentopts .= ",hl_lines='{$opt['hl_lines']}'";
		}
		if ($opt['title'] != '') {
			 $pygmentopts .= ",title='{$opt['title']}'";
		}

		// Add pygment options
		$cmd .= " {$pygmentopts}";

		// finally add outfile
		$cmd .= " -o {$filepath}";

		// Call pygmentize
		$pygment_descriptors = array(
			0 => array('pipe', 'r'),
			1 => array('pipe', 'w'),
			2 => array('pipe', 'a')
		);
		$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);
				$out = "<pre>pygmentize has errored. $err_out\n$std_out</pre>";
			}
		}
	}
	if (file_exists($filepath)) {
		$uploadpath = PUE(FmtPageName((IsEnabled($EnableDirectDownload, 1) && !$PmPygmentSecureAttachments)
					  ? "$UploadUrlFmt$UploadPrefixFmt/$upname"
					  : "{\$PageUrl}?action=download&upname=$upname", $pagename));
		if ($opt['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);
	}
}