📄 geshi.php
字号:
$attributes = ' class="st0"'; } $char = "<span$attributes>" . $hq; $i += strlen($hq) - 1; $HARDQUOTE_OPEN = true; $result .= $this->parse_non_string_part( $stuff_to_parse ); $stuff_to_parse = ''; } elseif ($char == $this->language_data['ESCAPE_CHAR'] && $STRING_OPEN != '') { // An escape character if (!$ESCAPE_CHAR_OPEN) { $ESCAPE_CHAR_OPEN = !$HARDQUOTE_OPEN; // true unless $HARDQUOTE_OPEN if ($HARDQUOTE_OPEN) foreach ($this->language_data['HARDESCAPE'] as $hard) { if (substr($part, $i, strlen($hard)) == $hard) { $ESCAPE_CHAR_OPEN = true; break; } } if ($ESCAPE_CHAR_OPEN && $this->lexic_permissions['ESCAPE_CHAR']) { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][0] . '"'; } else { $attributes = ' class="es0"'; } $char = "<span$attributes>" . $char; if (substr($code, $i + 1, 1) == "\n") { // escaping a newline, what's the point in putting the span around // the newline? It only causes hassles when inserting line numbers $char .= '</span>'; $ESCAPE_CHAR_OPEN = false; } } } else { $ESCAPE_CHAR_OPEN = false; if ($this->lexic_permissions['ESCAPE_CHAR']) { $char .= '</span>'; } } } elseif ($ESCAPE_CHAR_OPEN) { if ($this->lexic_permissions['ESCAPE_CHAR']) { $char .= '</span>'; } $ESCAPE_CHAR_OPEN = false; $test_str = $char; } elseif ($STRING_OPEN == '') { // Is this a multiline comment? foreach ($this->language_data['COMMENT_MULTI'] as $open => $close) { $com_len = strlen($open); $test_str = substr( $part, $i, $com_len ); $test_str_match = $test_str; if ($open == $test_str) { $COMMENT_MATCHED = true; //@todo If remove important do remove here if ($this->lexic_permissions['COMMENTS']['MULTI'] || $test_str == GESHI_START_IMPORTANT) { if ($test_str != GESHI_START_IMPORTANT) { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS']['MULTI'] . '"'; } else { $attributes = ' class="coMULTI"'; } $test_str = "<span$attributes>" . @htmlspecialchars($test_str, ENT_COMPAT, $this->encoding); } else { if (!$this->use_classes) { $attributes = ' style="' . $this->important_styles . '"'; } else { $attributes = ' class="imp"'; } // We don't include the start of the comment if it's an // "important" part $test_str = "<span$attributes>"; } } else { $test_str = @htmlspecialchars($test_str, ENT_COMPAT, $this->encoding); } $close_pos = strpos( $part, $close, $i + strlen($close) ); if ($close_pos === false) { $close_pos = strlen($part); } // Short-cut through all the multiline code $rest_of_comment = @htmlspecialchars(substr($part, $i + $com_len, $close_pos - $i), ENT_COMPAT, $this->encoding); if (($this->lexic_permissions['COMMENTS']['MULTI'] || $test_str_match == GESHI_START_IMPORTANT) && ($this->line_numbers != GESHI_NO_LINE_NUMBERS || count($this->highlight_extra_lines) > 0)) { // strreplace to put close span and open span around multiline newlines $test_str .= str_replace("\n", "</span>\n<span$attributes>", $rest_of_comment); } else { $test_str .= $rest_of_comment; } if ($this->lexic_permissions['COMMENTS']['MULTI'] || $test_str_match == GESHI_START_IMPORTANT) { $test_str .= '</span>'; } $i = $close_pos + $com_len - 1; // parse the rest $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; break; } } // If we haven't matched a multiline comment, try single-line comments if (!$COMMENT_MATCHED) { foreach ($this->language_data['COMMENT_SINGLE'] as $comment_key => $comment_mark) { $com_len = strlen($comment_mark); $test_str = substr($part, $i, $com_len); if ($this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS]) { $match = ($comment_mark == $test_str); } else { $match = (strtolower($comment_mark) == strtolower($test_str)); } if ($match) { $COMMENT_MATCHED = true; if ($this->lexic_permissions['COMMENTS'][$comment_key]) { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment_key] . '"'; } else { $attributes = ' class="co' . $comment_key . '"'; } $test_str = "<span$attributes>" . @htmlspecialchars($this->change_case($test_str), ENT_COMPAT, $this->encoding); } else { $test_str = @htmlspecialchars($test_str, ENT_COMPAT, $this->encoding); } $close_pos = strpos($part, "\n", $i); $oops = false; if ($close_pos === false) { $close_pos = strlen($part); $oops = true; } $test_str .= @htmlspecialchars(substr($part, $i + $com_len, $close_pos - $i - $com_len), ENT_COMPAT, $this->encoding); if ($this->lexic_permissions['COMMENTS'][$comment_key]) { $test_str .= "</span>"; } // Take into account that the comment might be the last in the source if (!$oops) { $test_str .= "\n"; } $i = $close_pos; // parse the rest $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; break; } } } } elseif ($STRING_OPEN != '') { // Otherwise, convert it to HTML form if (strtolower($this->encoding) == 'utf-8') { //only escape <128 (we don't want to break multibyte chars) if (ord($char) < 128) { $char = @htmlspecialchars($char, ENT_COMPAT, $this->encoding); } } else { //encode everthing $char = @htmlspecialchars($char, ENT_COMPAT, $this->encoding); } } // Where are we adding this char? if (!$COMMENT_MATCHED) { if (($STRING_OPEN == '') && !$CLOSE_STRING) { $stuff_to_parse .= $char; } else { $result .= $char; $CLOSE_STRING = false; } } else { $result .= $test_str; $COMMENT_MATCHED = false; } } // Parse the last bit $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; } else { $result .= @htmlspecialchars($part, ENT_COMPAT, $this->encoding); } // Close the <span> that surrounds the block if ($this->strict_mode && $this->language_data['STYLES']['SCRIPT'][$script_key] != '' && $this->lexic_permissions['SCRIPT']) { $result .= '</span>'; } } else { // Else not a block to highlight $result .= @htmlspecialchars($part, ENT_COMPAT, $this->encoding); } } // Parse the last stuff (redundant?) $result .= $this->parse_non_string_part($stuff_to_parse); // Lop off the very first and last spaces $result = substr($result, 1, -1); // Are we still in a string? if ($STRING_OPEN) { $result .= '</span>'; } // We're finished: stop timing $this->set_time($start_time, microtime()); return $this->finalise($result); } /** * Swaps out spaces and tabs for HTML indentation. Not needed if * the code is in a pre block... * * @param string The source to indent * @return string The source with HTML indenting applied * @since 1.0.0 * @access private */ function indent ($result) { /// Replace tabs with the correct number of spaces if (false !== strpos($result, "\t")) { $lines = explode("\n", $result); foreach ($lines as $key => $line) { if (false === strpos($line, "\t")) { $lines[$key] = $line; continue; } $pos = 0; $tab_width = $this->tab_width; $length = strlen($line); $result_line = ''; $IN_TAG = false; for ($i = 0; $i < $length; $i++) { $char = substr($line, $i, 1); // Simple engine to work out whether we're in a tag. // If we are we modify $pos. This is so we ignore HTML // in the line and only workout the tab replacement // via the actual content of the string // This test could be improved to include strings in the // html so that < or > would be allowed in user's styles // (e.g. quotes: '<' '>'; or similar) if ($IN_TAG && '>' == $char) { $IN_TAG = false; $result_line .= '>'; ++$pos; } elseif (!$IN_TAG && '<' == $char) { $IN_TAG = true; $result_line .= '<'; ++$pos; } elseif (!$IN_TAG && '&' == $char) { $substr = substr($line, $i + 3, 4); //$substr_5 = substr($line, 5, 1); $posi = strpos($substr, ';'); if (false !== $posi) { $pos += $posi + 3; } $result_line .= '&'; } elseif (!$IN_TAG && "\t" == $char) { $str = ''; // OPTIMISE - move $strs out. Make an array: // $tabs = array( // 1 => ' ', // 2 => ' ', // 3 => ' ' etc etc // to use instead of building a string every time $strs = array(0 => ' ', 1 => ' '); for ($k = 0; $k < ($tab_width - (($i - $pos) % $tab_width)); $k++) $str .= $strs[$k % 2]; $result_line .= $str; //$pos--; $pos++; //$pos -= $tab_width-1; if (false === strpos($line, "\t", $i + 1)) { //$lines[$key] = $result_line; $result_line .= substr($line, $i + 1); break; } } elseif ( $IN_TAG ) { ++$pos; $result_line .= $char; } else { $result_line .= $char; //++$pos; } } $lines[$key] = $result_line; } $result = implode("\n", $lines); } // Other whitespace $result = str_replace(' ', ' ', $result); $result = str_replace(' ', ' ', $result); $result = str_replace("\n ", "\n ", $result); if ($this->line_numbers == GESHI_NO_LINE_NUMBERS) { $result = nl2br($result); } return $result; } /** * Changes the case of a keyword for those languages where a change is asked for * * @param string The keyword to change the case of * @return string The keyword with its case changed * @since 1.0.0 * @access private */ function change_case ($instr) { if ($this->language_data['CASE_KEYWORDS'] == GESHI_CAPS_UPPER) { return strtoupper($instr); } elseif ($this->language_data['CASE_KEYWORDS'] == GESHI_CAPS_LOWER) { return strtolower($instr); } return $instr; } /** * Adds a url to a keyword where needed. * * @param string The keyword to add the URL HTML to * @param int What group the keyword is from * @param boolean Whether to get the HTML for the start or end * @return The HTML for either the start or end of the HTML <a> tag * @since 1.0.2 * @access private * @todo Get rid of ender */ function add_url_to_keyword ($keyword, $group, $start_or_end) { if (isset($this->language_data['URLS'][$group]) && $this->language_data['URLS'][$group] != '' && substr($keyword, 0, 5) != '</') { // There is a base group for this keyword if ($start_or_end == 'BEGIN') { // HTML workaround... not good form (tm) but should work for 1.0.X if ($keyword != '') { // Old system: strtolower //$keyword = ( $this->language_data['CASE_SENSITIVE'][$group] ) ? $keyword : strtolower($keyword); // New system: get keyword from language file to get correct case foreach ($this->language_data['KEYWORDS'][$group] as $word) { if (strtolower($word) == strtolower($keyword)) { break; } } $word = ( substr($word, 0, 4) == '<' ) ? substr($word, 4) : $word; $word = ( substr($word, -4) == '>' ) ? substr($word, 0, strlen($word) - 4) : $word; if (!$word) return ''; return '<|UR1|"' . str_replace( array('{FNAME}', '.'), array(@htmlspecialchars($word, ENT_COMPAT, $this->encoding), '<DOT>'), $this->language_data['URLS'][$group] ) . '">'; } return ''; // HTML fix. Again, dirty hackage... } elseif (!($this->language == 'html4strict' && '>' == $keyword)) { return '</a>'; } } } /** * Takes a string that has no strings or comments in it, and highlights * stuff like keywords, numbers and methods. * * @param string The string to parse for keyword, numbers etc. * @since 1.0.0 * @access private * @todo BUGGY! Why? Why not build string and return? */ function parse_non_string_part (&$stuff_to_parse) { $stuff_to_parse = ' ' . @htmlspecialchars($stuff_to_parse, ENT_COMPAT, $this->encoding); $stuff_to_parse_pregquote = preg_quote($stuff_to_parse, '/'); $func = '$this->change_case'; $func2 = '$this->add_url_to_keyword'; // // Regular expressions // foreach ($this->language_data['REGEXPS'] as $key => $regexp) { if ($this->lexic_permissions['REGEXPS'][$key]) { if (is_array($regexp)) { $stuff_to_parse = preg_replace( "/" . str_replace('/', '\/', $regexp[GESHI_SEARCH]) . "/{$regexp[GESHI_MODIFIERS]}", "{$regexp[GESHI_BEFORE]}<|!REG3XP$key!>{$regexp[GESHI_REPLACE]}|>{$regexp[GESHI_AFTER]}", $stuff_to_parse ); } else { $stuff_to_parse = preg_replace( "/(" . str_replace('/', '\/', $regexp) . ")/", "<|!REG3XP$key!>\\1|>", $stuff_to_parse); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -