Советы по внедрению простого регулярного выражения (для разбора bbcode / geshi) - PullRequest
0 голосов
/ 17 ноября 2010

Я сделал программное обеспечение для личных заметок на PHP, чтобы я мог хранить и упорядочивать свои заметки, и хотел иметь хороший простой формат для их записи.

Я сделал это в Markdown, но обнаружил, что это немногосбивает с толку и не было простой подсветки синтаксиса, поэтому я раньше делал bbcode и хотел реализовать это.

Теперь для GeSHi, который я действительно хочу реализовать (подсветка синтаксиса), требуется самый простой код, подобный этому:

$geshi = new GeSHi($sourcecode, $language);
$geshi->parse_code();

Теперь это самая простая часть, но я хочу, чтобы мой bbcode вызывал ее.

Мое текущее регулярное выражение соответствует выдуманному [syntax = cpp][/ синтаксис] bbcode выглядит следующим образом:

preg_replace('#\[syntax=(.*?)\](.*?)\[/syntax\]#si' , 'geshi(\\2,\\1)????', text);

Вы заметите, что я фиксирую язык и содержание, как я могу подключить его к коду GeSHi?

preg_replaceпросто можно заменить его строкой, а не «выражением», я не уверен, как использовать эти две строки кода для GeSHi там с захваченными данными ..

Я действительно взволновант этот проект и хочу преодолеть это.

Ответы [ 3 ]

2 голосов
/ 17 ноября 2010

Мне кажется, вы уже правильно поняли регулярное выражение.Ваша проблема заключается в вызове, поэтому я предлагаю сделать функцию-обертку:

function geshi($src, $l) {
    $geshi = new GeSHi($sourcecode, $language);
    $geshi->parse_code();
    return $geshi->how_do_I_get_the_results();
}

Теперь этого обычно достаточно, но исходный код, скорее всего, сам содержит одиночные или двойные кавычки.Поэтому вы не можете написать preg_replace(".../e", "geshi('$2','$1')", ...) так, как вам нужно.(Обратите внимание, что для '$ ​​1' и '$ 2' нужны кавычки, потому что preg_replace просто заменяет заполнители $ 1, $ 2, но это должен быть действительный встроенный код php).

Вот почему вам нужно использовать preg_replace_callbackпроблемы в коде замены / e exec.Так, например:

preg_replace_callback('#\[syntax=(.*?)\](.*?)\[/syntax\]#si' , 'geshi_replace', $text);

И я бы сделал вторую обертку, но вы можете объединить ее с исходным кодом:

function geshi_replace($uu) {
    return geshi($uu[2], $uu[1]);
}
2 голосов
/ 17 ноября 2010

Я написал этот класс некоторое время назад, причина этого в том, чтобы позволить легкую настройку / разбор.Может быть, немного излишним, но работает хорошо, и мне нужно было излишним для моего приложения.Использование довольно просто:

$geshiH = new Geshi_Helper();
$text = $geshiH->geshi($text); // this assumes that the text should be parsed (ie inline syntaxes)

---- ИЛИ ----

$geshiH = new Geshi_Helper();
$text = $geshiH->geshi($text, $lang);  // assumes that you have the language, good for a snippets deal

Я должен был сделать некоторые из других пользовательских элементов, которые яимел, но не ожидал никаких синтаксических ошибок от прерывания, это должно работать.Не стесняйтесь использовать его.

<?php

require_once 'Geshi/geshi.php';

class Geshi_Helper 
{
    /**
     * @var array Array of matches from the code block.
     */
    private $_codeMatches = array();

    private $_token = "";

    private $_count = 1;

    public function __construct()
    {
        /* Generate a unique hash token for replacement) */
        $this->_token = md5(time() . rand(9999,9999999));
    }

    /**
     * Performs syntax highlights using geshi library to the content.
     *
     * @param string $content - The context to parse
     * @return string Syntax Highlighted content
     */
    public function geshi($content, $lang=null)
    {
        if (!is_null($lang)) {
            /* Given the returned results 0 is not set, adding the "" should make this compatible */
            $content = $this->_highlightSyntax(array("", strtolower($lang), $content));
        }else {
            /* Need to replace this prior to the code replace for nobbc */
            $content = preg_replace('~\[nobbc\](.+?)\[/nobbc\]~ie', '\'[nobbc]\' . strtr(\'$1\', array(\'[\' => \'&#91;\', \']\' => \'&#93;\', \':\' => \'&#58;\', \'@\' => \'&#64;\')) . \'[/nobbc]\'', $content);

            /* For multiple content we have to handle the br's, hence the replacement filters */
            $content = $this->_preFilter($content);

            /* Reverse the nobbc markup */
            $content = preg_replace('~\[nobbc\](.+?)\[/nobbc\]~ie', 'strtr(\'$1\', array(\'&amp;#91;\' => \'[\', \'&amp;#93;\' => \']\', \'&amp;#58;\' => \':\', \'&amp;#64;\' => \'@\'))', $content);

            $content = $this->_postFilter($content);
        }

        return $content;
    }

    /**
     * Performs syntax highlights using geshi library to the content.
     * If it is unknown the number of blocks, use highlightContent
     * instead.
     *
     * @param string $content - The code block to parse
     * @param string $language - The language to highlight with
     * @return string Syntax Highlighted content
     * @todo Add any extra / customization styling here.
     */
    private function _highlightSyntax($contentArray)
    {
        $codeCount = $contentArray[1];

        /* If the count is 2 we are working with the filter */
        if (count($contentArray) == 2) {
            $contentArray = $this->_codeMatches[$contentArray[1]];
        }

        /* for default [syntax] */
        if ($contentArray[1] == "")
            $contentArray[1] = "php";

        /* Grab the language */
        $language = (isset($contentArray[1]))?$contentArray[1]:'text';

        /* Remove leading spaces to avoid problems */
        $content = ltrim($contentArray[2]);

        /* Parse the code to be highlighted */
        $geshi = new GeSHi($content, strtolower($language));
        return $geshi->parse_code();
    }

    /**
     * Substitute the code blocks for formatting to be done without
     * messing up the code.
     *
     * @param array $match - Referenced array of items to substitute
     * @return string Substituted content
     */
    private function _substitute(&$match)
    {
        $index = sprintf("%02d", $this->_count++);
        $this->_codeMatches[$index] = $match;
        return "----" . $this->_token . $index . "----";
    }

    /**
     * Removes the code from the rest of the content to apply other filters.
     *
     * @param string $content - The content to filter out the code lines
     * @return string Content with code removed.
     */
    private function _preFilter($content)
    {
        return preg_replace_callback("#\s*\[syntax=(.*?)\](.*?)\[/syntax\]\s*#siU", array($this, "_substitute"), $content);
    }

    /**
     * Replaces the code after the filters have been ran.
     *
     * @param string $content - The content to replace the code lines
     * @return string Content with code re-applied.
     */
    private function _postFilter($content)
    {
        /* using dashes to prevent the old filtered tag being escaped */
        return preg_replace_callback("/----\s*" . $this->_token . "(\d{2})\s*----/si", array($this, "_highlightSyntax"), $content);
    }
}
?>
1 голос
/ 17 ноября 2010

Использовать preg_match:

$match = preg_match('#\[syntax=(.*?)\](.*?)\[/syntax\]#si', $text);
$geshi = new GeSHi($match[2], $match[1]);
...