示例#1
0
function convertLaTeX($tag, $file, $code)
{
    // get rid of things that should be HTML
    $code = preprocessCode($code);
    global $regex;
    // fix special characters (" should be " for \"e)
    $code = parseAccents(str_replace(""", "\"", $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;
}
示例#2
0
 private function printView()
 {
     $value = "";
     if ($this->tag["type"] == "chapter") {
         $part = getPart($this->tag["book_id"]);
         $value .= "<h3>Chapter " . $this->tag["book_id"] . ": " . $this->tag["name"] . "</h3>";
         $value .= "<p>This tag corresponds to <a href='" . href("chapter/" . $this->tag["book_id"]) . "'>Chapter " . $this->tag["book_id"] . ": " . parseAccents($this->tag["name"]) . "</a> of <a href='" . href("browse#" . partToIdentifier($part)) . "'>" . parseAccents($part) . "</a>, and contains no further text. To view the contents of the first section in this chapter, go to the next tag.</p>";
         $value .= "<p>This chapter contains the following tags</p>";
         $value .= "<div id='control'>";
         $value .= "<p><a href='#'><img src='" . href("js/jquery-treeview/images/minus.gif") . "'> Collapse all</a>";
         $value .= " ";
         $value .= "<a href='#'><img src='" . href("js/jquery-treeview/images/plus.gif") . "'> Expand all</a>";
         $value .= "</div>";
         $value .= "<div id='treeview'>";
         $value .= "<a href='" . href("tag/" . $this->tag["tag"]) . "'>Tag " . $this->tag["tag"] . "</a> points to Chapter " . $this->tag["book_id"] . ": " . parseAccents($this->tag["name"]);
         $value .= printToC($this->tag["book_id"]);
         $value .= "</div>";
         $value .= "<script type='text/javascript' src='" . href("js/chapter.js") . "'></script>";
     } else {
         // only display for non-chapters
         $value .= "<p id='code-link' class='toggle'><a href='#code'>code</a></p>";
         $value .= "<blockquote class='rendered'>";
         $value .= convertLaTeX($this->tag["tag"], $this->tag["file"], $this->tag["value"]);
         // handle footnotes
         global $footnotes;
         $value .= "<div class='footnotes'>";
         $value .= "<ol>";
         foreach ($footnotes as $i => $footnote) {
             $value .= "<li class='footnote' id='fn:" . $i . "'>" . $footnote . "<a href='#fnref:" . $i . "' title='return to main text'> &uarr;</a>";
         }
         $value .= "</ol>";
         $value .= "</div>";
         $value .= "</blockquote>";
     }
     // only display for non-chapters
     if ($this->tag["type"] != "chapter") {
         $value .= "<p id='rendered-link' class='toggle'><a href='#rendered'>view</a></p>";
         $value .= "<div id='code'>";
         $value .= "<p>The code snippet corresponding to this tag is a part of the file <a href='https://github.com/stacks/stacks-project/blob/master/" . $this->tag["file"] . ".tex'><var>" . $this->tag["file"] . ".tex</var></a> and is located in <a href='https://github.com/stacks/stacks-project/blob/master/" . $this->tag["file"] . ".tex#L" . $this->tag["begin"] . "-" . $this->tag["end"] . "'>lines " . $this->tag["begin"] . "&ndash;" . $this->tag["end"] . "</a> (see <a href='" . href("tags#stacks-epoch") . "'>updates</a> for more information).";
         $value .= "<pre><code>";
         $code = preprocessCode($this->tag["value"]);
         // link labels to the corresponding tag
         $count = preg_match_all('/\\\\label{([\\w-\\*]+)}/', $code, $references);
         for ($i = 0; $i < $count; ++$i) {
             $code = str_replace($references[0][$i], "\\label{<a href='" . href("tag/" . getTagWithLabel($this->tag["file"] . "-" . $references[1][$i])) . "'>" . $references[1][$i] . "</a>}", $code);
         }
         $value .= $code;
         $value .= "</code></pre>";
         $value .= "</div>";
     }
     $value .= $this->printNavigation();
     return $value;
 }