Deprecated: Assigning the return value of new by reference is deprecated in /home/heungsub/blog/wp-settings.php on line 512 Deprecated: Assigning the return value of new by reference is deprecated in /home/heungsub/blog/wp-settings.php on line 527 Deprecated: Assigning the return value of new by reference is deprecated in /home/heungsub/blog/wp-settings.php on line 534 Deprecated: Assigning the return value of new by reference is deprecated in /home/heungsub/blog/wp-settings.php on line 570 Deprecated: Assigning the return value of new by reference is deprecated in /home/heungsub/blog/wp-includes/cache.php on line 103 Deprecated: Assigning the return value of new by reference is deprecated in /home/heungsub/blog/wp-includes/query.php on line 61 Deprecated: Assigning the return value of new by reference is deprecated in /home/heungsub/blog/wp-includes/theme.php on line 1109 PHP « Heungsub Blog

Posts Tagged ‘PHP’

Markdown 코드 구문강조

Monday, June 8th, 2009

블로그에 올린 코드블록에 구문강조가 안되니 보기 흉하더랍니다. 그래서 간단히 Syntax Highlighting in JavaScript(이하 SHJS)를 붙여보았습니다. 포스팅 작성 시 다음과 같이 입력하면 pre/@class에 따라 SHJS가 해당 언어의 구문강조 규칙을 적용해줍니다.

<pre class="sh_javascript_dom"><code>
alert('Heung, world!');
</code></pre>

그런데 HTML 코드를 삽입하려니 굉장히 불편합니다.

<pre class="sh_html"><code>
&lt;p&gt;Heung, world!&lt;/p&gt;
</code></pre>

HTML 엔터티를 손으로 써야하니 편집 시 가독성도 나빠지고 실수도 자주 할 것 같습니다. 그래서 제 블로그에서 사용하고 있는 Markdown for WordPress and bbPress를 확장하기로 했습니다. 다음과 같이 코드 블록 첫째 줄에 #!lang이라고 적으면 해당 언어의 구문강조 규칙이 적용되도록 말이죠.

    #!html
    <p>Heung, world!</p>

확장을 위해 ~/wp-content/plugins/markdown/markdown.php에 있는 Markdown_Parser 클래스의 doCodeBlock 메소드와 _doCodeBlocks_callback 메소드를 다음과 같이 수정했습니다.

function doCodeBlocks($text) {
#
#   Process Markdown `<pre><code>` blocks.
#
    $text = preg_replace_callback('{
            (?:\n\n|\A\n?)
            [ ]{'.$this->tab_width.'}(?:\#!([^\s]+))?\n
            (
              (?>
                [ ]{'.$this->tab_width.'}
                .*\n+
              )+
            )
            ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)
        }xm',
        array(&$this, '_doCodeBlocks_callback'), $text);

    return $text;
}
function _doCodeBlocks_callback($matches) {
    $langs = array(
        'c++' => 'cpp',
        'cxx' => 'cpp',
        'c#' => 'csharp',
        'js' => 'javascript_dom',
        'javascript' => 'javascript_dom',
        'bash' => 'sh',
        'shell' => 'sh'
    );
    $lang = strtolower($matches[1]);
    $codeblock = $matches[2];

    $codeblock = $this->outdent($codeblock);
    $codeblock = htmlspecialchars(
        $codeblock,
        ENT_NOQUOTES
    );

    # trim leading newlines and trailing newlines
    $codeblock = preg_replace(
        '/\A\n+|\n+\z/',
        '',
        $codeblock
    );

    $markup = "<pre";
    if ($lang) {
        if (array_key_exists($lang, $langs))
            $lang = $langs[$lang];
        $markup .= " class=\"sh_{$lang}\"";
    }
    $markup .= "><code>$codeblock\n</code></pre>";
    return "\n\n".$this->hashBlock($markup)."\n\n";
}

잘 되는군요. :)