Example #1
0
/**
 * Deals with the [macro parameters] substitutions
 *
 * See the macroList plugin for details
 *
 * @param string $text
 * @return string
 */
function applyMacros($text)
{
    $content_macros = getMacros();
    preg_match_all('/\\[(\\w+)(.*?)\\]/i', $text, $instances);
    foreach ($instances[0] as $instance => $macro_instance) {
        $macroname = strtoupper($instances[1][$instance]);
        if (array_key_exists($macroname, $content_macros)) {
            $macro = $content_macros[$macroname];
            $p = $instances[2][$instance];
            $data = NULL;
            $class = $macro['class'];
            if ($p) {
                $p = trim(utf8::sanitize(str_replace(" ", ' ', strip_tags($p))));
                //	remove hard spaces and invalid characters
                $p = preg_replace("~\\s+=\\s+(?=(?:[^\"]*+\"[^\"]*+\")*+[^\"]*+\$)~", "=", $p);
                //	deblank assignment operator
                preg_match_all("~'[^'\"]++'|\"[^\"]++\"|[^\\s]++~", $p, $l);
                //	parse the parameter list
                $parms = array();
                $k = 0;
                foreach ($l[0] as $s) {
                    if ($s != ',') {
                        $parms[$k++] = trim($s, '\'"');
                        //	remove any quote marks
                    }
                }
            } else {
                $parms = array();
            }
            $parameters = array();
            if (!empty($macro['params'])) {
                $err = false;
                foreach ($macro['params'] as $key => $type) {
                    $data = false;
                    if (array_key_exists($key, $parms)) {
                        switch (trim($type, '*')) {
                            case 'int':
                                if (is_numeric($parms[$key])) {
                                    $parameters[] = (int) $parms[$key];
                                } else {
                                    $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d should be a number.'), trim($macro_instance, '[]'), $key + 1) . '</span>';
                                    $class = 'error';
                                }
                                break;
                            case 'string':
                                if (is_string($parms[$key])) {
                                    $parameters[] = $parms[$key];
                                } else {
                                    $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d should be a string.'), trim($macro_instance, '[]'), $key + 1) . '</span>';
                                    $class = 'error';
                                }
                                break;
                            case 'bool':
                                switch (strtolower($parms[$key])) {
                                    case "true":
                                        $parameters[] = true;
                                        break;
                                    case "false":
                                        $parameters[] = false;
                                        break;
                                    default:
                                        $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d should be <code>true</code> or <code>false</code>.'), trim($macro_instance, '[]'), $key + 1) . '</span>';
                                        $class = 'error';
                                        break;
                                }
                                break;
                            case 'array':
                                $l = array_slice($parms, $key);
                                $parms = array();
                                foreach ($l as $key => $p) {
                                    $x = explode('=', $p);
                                    if (count($x) == 2) {
                                        $parms[$x[0]] = $x[1];
                                    } else {
                                        $parms[$key] = $x[0];
                                    }
                                }
                                $parameters[] = $parms;
                                break;
                            default:
                                $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d is incorrectly defined.'), trim($macro_instance, '[]'), $key + 1) . '</span>';
                                $class = 'error';
                                break;
                        }
                    } else {
                        if (strpos($type, '*') === false) {
                            $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> parameter %2$d is missing.'), trim($macro_instance, '[]'), $key + 1) . '</span>';
                            $class = 'error';
                        }
                        break;
                    }
                }
            } else {
                if (!empty($p)) {
                    $class = 'error';
                    $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> macro does not take parameters'), trim($macro_instance, '[]')) . '</span>';
                }
            }
            switch ($class) {
                case 'error':
                    break;
                case 'function':
                case 'procedure':
                    if (is_callable($macro['value'])) {
                        if ($class == 'function') {
                            ob_start();
                            $data = call_user_func_array($macro['value'], $parameters);
                            if (empty($data)) {
                                $data = ob_get_contents();
                            }
                            ob_end_clean();
                        } else {
                            ob_start();
                            call_user_func_array($macro['value'], $parameters);
                            $data = ob_get_contents();
                            ob_end_clean();
                        }
                        if (empty($data)) {
                            $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> retuned no data'), trim($macro_instance, '[]')) . '</span>';
                        } else {
                            $data = "\n<!--Begin " . $macroname . "-->\n" . $data . "\n<!--End " . $macroname . "-->\n";
                        }
                    } else {
                        $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> <code>%2$s</code> is not callable'), trim($macro_instance, '[]'), $macro['value']) . '</span>';
                    }
                    break;
                case 'constant':
                    $data = "\n<!--Begin " . $macroname . "-->\n" . $macro['value'] . "\n<!--End " . $macroname . "-->\n";
                    break;
                case 'expression':
                    $expression = '$data = ' . $macro['value'];
                    $parms = array_reverse($parms, true);
                    preg_match_all('/\\$\\d+/', $macro['value'], $replacements);
                    foreach ($replacements as $rkey => $v) {
                        if (empty($v)) {
                            unset($replacements[$rkey]);
                        }
                    }
                    if (count($parms) == count($replacements)) {
                        foreach ($parms as $key => $value) {
                            $key++;
                            $expression = preg_replace('/\\$' . $key . '/', db_quote($value), $expression);
                        }
                        eval($expression);
                        if (!isset($data) || is_null($data)) {
                            $data = '<span class="error">' . sprintf(gettext('<em>[%1$s]</em> retuned no data'), trim($macro_instance, '[]')) . '</span>';
                        } else {
                            $data = "\n<!--Begin " . $macroname . "-->\n" . $data . "\n<!--End " . $macroname . "-->\n";
                        }
                    } else {
                        $data = '<span class="error">' . sprintf(ngettext('<em>[%1$s]</em> takes %2$d parameter', '<em>[%1$s]</em> takes %2$d parameters', count($replacements)), trim($macro_instance, '[]'), count($replacements)) . '</span>';
                    }
                    break;
            }
            $text = str_replace($macro_instance, $data, $text);
        }
    }
    return $text;
}
Example #2
0
function convertLaTeX($tag, $file, $code)
{
    // get rid of things that should be HTML
    $code = preprocessCode($code);
    global $regex;
    // fix special characters (&quot; should be " for \"e)
    $code = parseAccents(str_replace("&quot;", "\"", $code));
    // remove the reference environment
    $ignoredEnvironments = array("reference", "slogan", "history");
    foreach ($ignoredEnvironments as $environment) {
        $lines = explode("\n", $code);
        $result = "";
        $ignored = false;
        foreach ($lines as $line) {
            if ($line == "\\begin{" . $environment . "}") {
                $ignored = true;
            }
            if (!$ignored) {
                $result .= $line . "\n";
            }
            if ($line == "\\end{" . $environment . "}") {
                $ignored = false;
            }
        }
        $code = $result;
    }
    // all big environments with their corresponding markup
    $environments = array("lemma" => array("name" => "Lemma", "type" => "plain"), "definition" => array("name" => "Definition", "type" => "definition"), "remark" => array("name" => "Remark", "type" => "remark"), "remarks" => array("name" => "Remarks", "type" => "remark"), "example" => array("name" => "Example", "type" => "definition"), "theorem" => array("name" => "Theorem", "type" => "plain"), "exercise" => array("name" => "Exercise", "type" => "definition"), "situation" => array("name" => "Situation", "type" => "definition"), "proposition" => array("name" => "Proposition", "type" => "plain"));
    foreach ($environments as $environment => $information) {
        $count = preg_match_all("/\\\\begin\\{" . $environment . "\\}\n\\\\label\\{([\\w\\*\\-]*)\\}/", $code, $matches);
        for ($i = 0; $i < $count; $i++) {
            $label = $file . '-' . $matches[1][$i];
            // check whether the label exists in the database, if not we cannot supply either a link or a number unfortunately
            if (labelExists($label)) {
                $code = str_replace($matches[0][$i], "<div class='" . $information["type"] . "'><p><a class='environment-identification' href='" . href("tag/" . getTagWithLabel($label)) . "'>" . $information["name"] . " " . getIDWithLabel($label) . ".</a>", $code);
            } else {
                $code = str_replace($matches[0][$i], "<div class='" . $information["type"] . "'><p><span class='environment-identification'>" . $information["name"] . ".</span>", $code);
            }
        }
        // do the same for named environments
        $regexForNamed = "[\\p{L}\\p{Nd}\\?@\\s\$,.:()'N&#;\\-\\\\\$\"\\{\\}<>\\=\\/]+";
        $count = preg_match_all("/\\\\begin\\{" . $environment . "\\}\\[(" . $regexForNamed . ")\\]\n\\\\label\\{([\\w\\-]*)\\}/u", $code, $matches);
        for ($i = 0; $i < $count; $i++) {
            $label = $file . '-' . $matches[2][$i];
            // check whether the label exists in the database, if not we cannot supply either a link or a number unfortunately
            if (labelExists($label)) {
                $code = str_replace($matches[0][$i], "<div class='" . $information["type"] . "'><p><a class='environment-identification' href='" . href("tag/" . getTagWithLabel($label)) . "'>" . $information["name"] . " " . getIDWithLabel($label) . " <span class='named'>(" . $matches[1][$i] . ")</span>.</a>", $code);
            } else {
                $code = str_replace($matches[0][$i], "<div class='" . $information["type"] . "'><p><span class='environment-identification'>" . $information["name"] . " <span class='named'>(" . $matches[1][$i] . ")</span>.</span>", $code);
            }
        }
        $code = str_replace("\\end{" . $environment . "}", "</div>", $code);
    }
    $count = preg_match_all("/\\\\begin\\{equation\\}\n\\\\label\\{([\\w\\-]+)\\}\n/", $code, $matches);
    for ($i = 0; $i < $count; $i++) {
        $label = $file . '-' . $matches[1][$i];
        // check whether the label exists in the database, if not we cannot supply an equation number unfortunately
        if (labelExists($label)) {
            $code = str_replace($matches[0][$i], "\\begin{equation}\n\\tag{" . getIDWithLabel($label) . "}\n", $code);
        } else {
            $code = str_replace($matches[0][$i], "\\begin{equation}\n", $code);
        }
    }
    // sections etc.
    $count = preg_match_all("/\\\\section\\{(" . $regex . ")\\}\n\\\\label\\{([\\w\\-]+)\\}/u", $code, $matches);
    for ($i = 0; $i < $count; $i++) {
        $label = $file . '-' . $matches[2][$i];
        // check whether the label exists in the database, if not we cannot supply either a link or a number unfortunately
        if (labelExists($label)) {
            $code = str_replace($matches[0][$i], "<h3>" . getIDWithLabel($label) . ". " . $matches[1][$i] . "</h3>", $code);
        } else {
            $code = str_replace($matches[0][$i], "<h3>" . $matches[1][$i] . "</h3>", $code);
        }
    }
    $count = preg_match_all("/\\\\subsection\\{(" . $regex . ")\\}\n\\\\label\\{([\\w-]+)\\}/u", $code, $matches);
    for ($i = 0; $i < $count; $i++) {
        $label = $file . '-' . $matches[2][$i];
        $code = str_replace($matches[0][$i], "<h4><a class='environment-identification' href='" . href("tag/" . getTagWithLabel($label)) . "'>" . getIDWithLabel($label) . ". " . $matches[1][$i] . "</a></h4>", $code);
    }
    // remove remaining labels
    $code = preg_replace("/\\\\label\\{[\\w\\-]+\\}\n?/", "", $code);
    // remove \linebreak commands
    $code = preg_replace("/\\\\linebreak(\\[\\d?\\])?/", "", $code);
    // lines starting with % (tag 03NV for instance) should be removed
    $code = preg_replace("/\\%[\\w.]+/", "", $code);
    // these do not fit into the system above
    $code = str_replace("\\begin{center}", "<center>", $code);
    $code = str_replace("\\end{center}", "</center>", $code);
    $code = str_replace("\\begin{quote}", "<blockquote>", $code);
    $code = str_replace("\\end{quote}", "</blockquote>", $code);
    // proof environment
    $lines = explode("\n", $code);
    foreach ($lines as &$line) {
        // we have a named proof
        if (strpos($line, "\\begin{proof}[") === 0) {
            $start = strpos($line, "[") + 1;
            $end = strrpos($line, "]");
            $line = "<p><strong>" . substr($line, $start, $end - $start) . ".</strong>";
        }
    }
    $code = implode("\n", $lines);
    $code = str_replace("\\begin{proof}", "<p><strong>Proof.</strong>", $code);
    $code = str_replace("\\end{proof}", "<span style='float: right;'>\$\\square\$</span>", $code);
    // hyperlinks
    $code = preg_replace("/\\\\href\\{(.*)\\}\\{(" . $regex . ")\\}/u", "<a href=\"\$1\">\$2</a>", $code);
    $code = preg_replace("/\\\\url\\{(.*)\\}/", "<a href=\"\$1\">\$1</a>", $code);
    // emphasis
    $code = parseBoldface($code);
    $code = parseItalics($code);
    $code = preg_replace("/\\{\\\\em (" . $regex . ")\\}/u", "<em>\$1</em>", $code);
    $code = preg_replace("/\\\\emph\\{(" . $regex . ")\\}/u", "<em>\$1</em>", $code);
    // parse \cite commands
    $code = parseCitations($code);
    // filter \input{chapters}
    $code = str_replace("\\input{chapters}", "", $code);
    // enumerates etc.
    $code = str_replace("\\begin{enumerate}", "<ol>", $code);
    $code = str_replace("\\end{enumerate}", "</ol>", $code);
    $code = str_replace("\\begin{itemize}", "<ul>", $code);
    $code = str_replace("\\end{itemize}", "</ul>", $code);
    $code = preg_replace("/\\\\begin{list}(.*)\n/", "<ul>\n", $code);
    // unfortunately I have to ignore information in here
    $code = str_replace("\\end{list}", "</ul>", $code);
    $code = preg_replace("/\\\\item\\[(.*)\\]/U", "<li class='custom'>\$1&nbsp;&nbsp;&nbsp;", $code);
    // TODO: Correctly use the label here
    $code = str_replace("\\item", "<li>", $code);
    // let HTML be aware of paragraphs
    #$code = str_replace("\n\n", "\n", $code);
    $code = str_replace("\\smallskip", "", $code);
    $code = str_replace("\\medskip", "", $code);
    $code = str_replace("\\noindent", "<p>", $code);
    // parse references
    //$code = preg_replace('/\\\ref\{(.*)\}/', "$1", $code);
    $references = array();
    // don't escape in math mode because XyJax doesn't like that, and fix URLs too
    $lines = explode("\n", $code);
    $math_mode = false;
    // variable tracking what level of nesting of lists we are at
    $list_mode = 0;
    foreach ($lines as &$line) {
        // $$ is a toggle
        if (startsWith("\$\$", $line)) {
            $math_mode = !$math_mode;
        }
        // after the end of a nested set of lists, we need to start a new paragraph.
        // TODO: Use this code to get numbering of paragraphs correct (mimick what latex does)
        if ($line == '<ol>' || $line == '<ul>') {
            $list_mode = $list_mode + 1;
        }
        if ($line == '</ol>' || $line == '</ul>') {
            $list_mode = $list_mode - 1;
            if ($list_mode == 0) {
                $line = $line . "\n<p>";
            }
        }
        $environments = array('equation', 'align', 'align*', 'eqnarray', 'eqnarray*');
        foreach ($environments as $environment) {
            if (startsWith('\\begin{' . $environment . '}', $line)) {
                $math_mode = true;
            }
            if (startsWith('\\end{' . $environment . '}', $line)) {
                $math_mode = false;
            }
        }
        if ($math_mode) {
            $line = str_replace('&gt;', '>', $line);
            $line = str_replace('&lt;', '<', $line);
            $line = str_replace('&amp;', '&', $line);
            $line = str_replace('&nbsp;', '~', $line);
            // we replace links in math mode by plain text as mathjax cannot handle <a href=""></a>
            $count = preg_match_all('/\\\\ref{<a href=\\"([\\w\\/]+)\\">([\\w-\\*]+)<\\/a>}/', $line, $matches);
            for ($j = 0; $j < $count; $j++) {
                $line = str_replace($matches[0][$j], getID(substr($matches[1][$j], -4)), $line);
            }
        }
    }
    $code = implode("\n", $lines);
    // we replace the text in a link (definition-strict) by its ID (Definition 11.13.3)
    $count = preg_match_all('/\\\\ref{<a href=\\"([\\w\\/]+)\\">([\\w-\\*]+)<\\/a>}/', $code, $references);
    for ($i = 0; $i < $count; ++$i) {
        $code = str_replace($references[0][$i], "<a href='" . $references[1][$i] . "'>" . getID(substr($references[1][$i], -4)) . "</a>", $code);
    }
    // fix macros
    $macros = getMacros();
    $code = preg_replace(array_keys($macros), array_values($macros), $code);
    /* the following line removes footnotes if there are any, adds links to
         suitable targets (html) and stores the footnote contents in the global variable
         we do this at the end so that everything is already converted suitably
      */
    $code = parseFootnotes($code);
    return $code;
}
Example #3
0
	<div id="main">
		<?php 
printTabs();
?>
		<div id="content">
			<div id="container">
				<?php 
printSubtabs();
?>
				<div class="tabbox">
					<h1><?php 
echo gettext('Content Macros');
?>
</h1>
					<?php 
$macros = getMacros();
ksort($macros);
if (empty($macros)) {
    echo gettext('No macros have been defined.');
} else {
    ?>
						<div>
							<p><?php 
    echo gettext('These Content macros can be used to insert Zenphoto items as described into <em>descriptions</em>, <em>zenpage content</em>, and <em>zenpage extra content</em>.</p> <p>Replace any parameters (<em>%d</em>) with the appropriate value.');
    ?>
</p>
							<p><?php 
    echo gettext('Parameter types:');
    ?>
</p>
							<ol>
Example #4
0
							</label>
							<?php 
            }
        } elseif (isImageVideo($obj)) {
            $content_macros = getMacros();
            if (array_key_exists('MEDIAPLAYER', $content_macros)) {
                ?>
							<label class="nowrap"><input type="radio" name="link" value="player" id="link_image_none" onchange="zenchange();" /><?php 
                echo gettext('Mediaplayer macro');
                ?>
</label>
							<?php 
            }
        } else {
            if (!$imagef) {
                $content_macros = getMacros();
                if (array_key_exists('SLIDESHOW', $content_macros)) {
                    ?>
							<label class="nowrap"><input type="radio" name="link" value="show" id="link_image_none" onchange="zenchange();" /><?php 
                    echo gettext('Slideshow macro');
                    ?>
</label>
							<?php 
                }
            }
        }
        ?>

					<br />
					<?php 
        if ($picture) {
Example #5
0
function parseComment($comment)
{
    // parse \ref{}, but only when the line is not inside a code fragment
    $lines = explode("\n", $comment);
    foreach ($lines as &$line) {
        // check whether the line is a code fragment or not
        if (substr($line, 0, 4) != '    ') {
            $line = parseReferences($line);
        }
    }
    $comment = implode($lines, "\n");
    // fix underscores and asterisks (all underscores in math mode will be escaped
    $result = '';
    $mathmode = false;
    foreach (str_split($comment) as $position => $character) {
        // match math mode (\begin{equation}\end{equation} goes fine mysteriously)
        if ($character == "\$") {
            // handle $$ correctly
            if ($position + 1 < strlen($comment) && $comment[$position + 1] != "\$") {
                $mathmode = !$mathmode;
            }
        }
        // replace unescaped underscores in math mode, the accessed position always exists because we had to enter math mode first
        if ($mathmode && $character == "_" && $comment[$position - 1] != "\\") {
            $result .= "\\_";
        } elseif ($mathmode && $character == "*" && $comment[$position - 1] != "\\") {
            $result .= "\\*";
        } else {
            $result .= $character;
        }
    }
    $comment = $result;
    // remove <>&"'
    $comment = htmlspecialchars($comment);
    // duplicate double backslashes
    $comment = str_replace("\\\\", "\\\\\\\\", $comment);
    // apply Markdown (i.e. we get an almost finished HTML string)
    $comment = Markdown($comment);
    // Firefox liked to throw in some &nbsp;'s, but I believe this particular fix is redundant now
    $comment = str_replace("&nbsp;", ' ', $comment);
    // Markdown messes up { and }, replace the ASCII codes by the actual characters for MathJax to pick it up
    $comment = str_replace("&#123;", "\\{", $comment);
    $comment = str_replace("&#125;", "\\}", $comment);
    // fix macros
    $macros = getMacros();
    $comment = preg_replace(array_keys($macros), array_values($macros), $comment);
    return $comment;
}