PHP语法高亮显示

39
我正在寻找一个可以自定义的PHP语法高亮引擎(即我可以为新语言提供自己的分词器),并且能够同时处理多种语言(即在同一输出页面上)。这个引擎必须与CSS类很好地配合使用,即它应该通过插入带有class属性的<span>元素来格式化输出。如果具有可扩展的架构,则额外加分。
不是要寻找客户端语法高亮脚本(JavaScript)。
到目前为止,我被困在GeSHi中。不幸的是,GeSHi因为几个原因而失败得非常惨。主要原因是不同的语言文件定义了完全不同、不一致的样式。我花费数小时尝试将不同的语言定义重构成公共项,但由于大多数定义文件本身相当糟糕,所以我最终想切换引擎。
理想情况下,我想要一个类似于CodeRayPygments或JavaScript的dp.SyntaxHighlighter的API。
澄清一下:我正在寻找用PHP编写的代码高亮软件,而不是用于PHP的代码高亮软件(因为我需要从PHP内部使用它)。

1
如果您列出需要语法高亮的编程语言,将会更有帮助。 - Kibbee
我明确地不想限制这个。目标语言并不重要:任何值得一试的语法高亮引擎都可以扩展以处理(几乎)所有语言。我不寻找仅适用于微小子集的专门版本。 - Konrad Rudolph
我编写了一个围绕Pygments库的PHP封装器,支持大量语言。我在几个网站上使用它,效果很棒,也许有人会觉得它有用:https://github.com/igorpan/PHPygmentizator - user2742648
10个回答

48

由于没有现有的工具符合我的需求,我编写了自己的工具。惊奇的是:

Hyperlight

使用非常简单:只需使用

 <?php hyperlight($code, 'php'); ?>

用于突出显示代码。编写新语言定义相对容易,只需使用正则表达式和功能强大但简单的状态机即可。顺便说一句,我仍然需要很多定义,所以请随时贡献。


这很好。我希望它能检测到方法/构造函数以及变量声明中的类型。 - NateS
4
添加它并不困难。太赞了!这里是我通用的代码高亮工具,可以处理很多语言。已测试过:Java、C#、JavaScript、AS3、C、C++、Lua。 - NateS

10

http://softwaremaniacs.org/soft/highlight/是一个支持多种语言(Python、Ruby、Perl、PHP、XML、HTML、CSS、Django、Javascript、VBScript、Delphi、Java、C++、C#、Lisp、RenderMan(RSL和RIB)、Maya嵌入式语言、SQL、SmallTalk、Axapta、1C、Ini、Diff、DOS .bat、Bash)的PHP 语法高亮库。

它使用样式的标记。

它也已经被集成到dojo toolkit中(作为dojox项目:dojox.lang.highlight)。

严格来说,虽然不是运行Web服务器的最流行方式,但Javascript不仅在客户端实现,还有一些服务器端Javascript引擎/平台组合


在PHP中有默认函数: <?php highlight_string('<?php phpinfo(); ?>'); ?> 参考:http://www.tamildic.com/online-php-syntax-highlighter 工作测试工具 - Manikandan

9

我发现了这个用PHP编写的简单通用语法高亮器,在这里,并对其进行了一些修改:

<?php

/**
 * Original => http://phoboslab.org/log/2007/08/generic-syntax-highlighting-with-regular-expressions
 * Usage => `echo SyntaxHighlight::process('source code here');`
 */

class SyntaxHighlight {
    public static function process($s) {
        $s = htmlspecialchars($s);

        // Workaround for escaped backslashes
        $s = str_replace('\\\\','\\\\<e>', $s); 

        $regexp = array(

            // Comments/Strings
            '/(
                \/\*.*?\*\/|
                \/\/.*?\n|
                \#.[^a-fA-F0-9]+?\n|
                \&lt;\!\-\-[\s\S]+\-\-\&gt;|
                (?<!\\\)&quot;.*?(?<!\\\)&quot;|
                (?<!\\\)\'(.*?)(?<!\\\)\'
            )/isex' 
            => 'self::replaceId($tokens,\'$1\')',

            // Punctuations
            '/([\-\!\%\^\*\(\)\+\|\~\=\`\{\}\[\]\:\"\'<>\?\,\.\/]+)/'
            => '<span class="P">$1</span>',

            // Numbers (also look for Hex)
            '/(?<!\w)(
                (0x|\#)[\da-f]+|
                \d+|
                \d+(px|em|cm|mm|rem|s|\%)
            )(?!\w)/ix'
            => '<span class="N">$1</span>',

            // Make the bold assumption that an
            // all uppercase word has a special meaning
            '/(?<!\w|>|\#)(
                [A-Z_0-9]{2,}
            )(?!\w)/x'
            => '<span class="D">$1</span>',

            // Keywords
            '/(?<!\w|\$|\%|\@|>)(
                and|or|xor|for|do|while|foreach|as|return|die|exit|if|then|else|
                elseif|new|delete|try|throw|catch|finally|class|function|string|
                array|object|resource|var|bool|boolean|int|integer|float|double|
                real|string|array|global|const|static|public|private|protected|
                published|extends|switch|true|false|null|void|this|self|struct|
                char|signed|unsigned|short|long
            )(?!\w|=")/ix'
            => '<span class="K">$1</span>',

            // PHP/Perl-Style Vars: $var, %var, @var
            '/(?<!\w)(
                (\$|\%|\@)(\-&gt;|\w)+
            )(?!\w)/ix'
            => '<span class="V">$1</span>'

        );

        $tokens = array(); // This array will be filled from the regexp-callback

        $s = preg_replace(array_keys($regexp), array_values($regexp), $s);

        // Paste the comments and strings back in again
        $s = str_replace(array_keys($tokens), array_values($tokens), $s);

        // Delete the "Escaped Backslash Workaround Token" (TM)
        // and replace tabs with four spaces.
        $s = str_replace(array('<e>', "\t"), array('', '    '), $s);

        return '<pre><code>' . $s . '</code></pre>';
    }

    // Regexp-Callback to replace every comment or string with a uniqid and save
    // the matched text in an array
    // This way, strings and comments will be stripped out and wont be processed
    // by the other expressions searching for keywords etc.
    private static function replaceId(&$a, $match) {
        $id = "##r" . uniqid() . "##";

        // String or Comment?
        if(substr($match, 0, 2) == '//' || substr($match, 0, 2) == '/*' || substr($match, 0, 2) == '##' || substr($match, 0, 7) == '&lt;!--') {
            $a[$id] = '<span class="C">' . $match . '</span>';
        } else {
            $a[$id] = '<span class="S">' . $match . '</span>';
        }
        return $id;
    }
}

?>

演示: http://phpfiddle.org/lite/code/1sf-htn


更新

我刚刚创建了一个我的JavaScript通用语法高亮器的PHP版本,链接在这里 → https://github.com/taufik-nurrohman/generic-syntax-highlighter/blob/master/generic-syntax-highlighter.php

使用方法:

<?php require 'generic-syntax-highlighter.php'; ?>
<pre><code><?php echo SH('&lt;div class="foo"&gt;&lt;/div&gt;'); ?></code></pre>

我喜欢它将语言信息存储在regexp数组中。如果您想获得更具体的高亮显示,应该很容易为不同的语言提供不同的regexp数组。 - spike.barnett
1
请将您的代码更新到 PHP 7。 - ManojKiran A

3

也许值得看一下Pear_TextHighlighter文档)。

我认为它默认情况下不会完全按照您想要的方式输出html,但它提供了广泛的定制功能(即,您可以创建不同的渲染器/解析器)。


2
我遇到了完全相同的问题,但是由于时间非常紧迫,而且需要真正好的代码覆盖率,所以我决定在 Pygments库周围编写一个PHP包装器。
它被称为 PHPygmentizator。它非常容易使用。我写了一个非常基本的 手册。由于PHP主要用于Web开发语言,因此我将结构从那个角度来看,使其非常容易在几乎任何类型的网站中实现。
它支持 配置文件,如果这还不够,并且有人需要在过程中修改一些内容,它还会触发 事件
“它的演示可以在我的博客上包含源代码的任何帖子上找到,例如this one。”
“使用默认配置,您只需提供一个以此格式为字符串:”
Any text here.

[pygments=javascript]
var a = function(ar1, ar2) {
    return null;
}
[/pygments]

Any text.

所以,它会突出显示标签之间的代码(标签可以在配置文件中自定义),并保留其余部分不变。
此外,我已经制作了一个语法识别库(它使用的算法可能被归类为贝叶斯概率),它可以自动识别编写的代码块使用的语言,并可以轻松地连接到PHPygmentizator的事件之一以提供自动语言识别。如果您向其提供足够的“学习”数据,它可以惊人地识别语言。我甚至测试过压缩的JavaScript和具有相似关键字和结构的语言,它从未犯过错误。我可能会在本周某个时候将其公开,因为我需要美化一下结构并编写一些基本文档。

谢谢,带有自动语言识别功能肯定会更好。但是包装Pygments是双刃剑:它支持大量的编程语言,但无法在共享托管的网站上使用。 - user2742648

1

4
当然,这只突出了 PHP 代码。此外,这个函数很糟糕,因为它根本不能定制。 - Konrad Rudolph
噢,你可以通过ini设置进行配置,例如highlight.comment :) - cweiske
1
此外,它输出的是内联样式而不是CSS类,这既难看又不符合OP的要求。 - Tom Auger
它并没有我认为的“配置”功能。你可以选择颜色,但除此之外你对行号、空白区域、高亮语言、交替行颜色、高亮行、高亮子部分以及其他许多在许多语法高亮器中常见的特性都无法控制。 - Bob Ray

1

但它只支持PHP代码,这并不是要求。 - Konrad Rudolph

1

可能有点晚了,但我一直在开发自己的PHP语法高亮库。它还处于早期阶段,但我正在我的博客上使用它来展示所有代码示例。

刚刚看了一下Hyperlight。它看起来很酷,但它做了一些相当疯狂的事情。嵌套循环,逐行处理等等。核心类超过1000行代码。

如果你对简单轻量级的东西感兴趣,请看看Nijikodo: http://www.craigiam.com/nijikodo


"核心类超过了1000行代码" 等等,什么?不,我会知道的。它要短得多 - 我只是试图将所有核心功能(即“几个”类)放入一个文件中以使其更易分发。回头来看,这是一个错误。此外,没有逐行处理。它基本上是一个正常的词法分析器(只是它还可以处理递归标记定义)。- 话虽如此,你的代码看起来也很好。我一定会看一下的。 - Konrad Rudolph

1

另一个选择是使用由Andre Simon开发的GPL Highlight GUI程序,该程序适用于大多数平台。它可以将PHP(和其他语言)转换为HTML、RTF、XML等格式,然后您可以将其剪切并粘贴到所需页面中。这样,处理只需要进行一次。

HTML也基于CSS,因此您可以根据自己的喜好更改样式。

个人而言,我使用dp.SyntaxHighlighter,但它使用客户端JavaScript,因此不符合您的需求。不过它确实有一个很好的Windows Live插件,我觉得很有用。


0
Krijn Hoetmer的PHP Highlighter提供了一个完全可定制的PHP类来突出显示PHP语法。它生成的HTML在严格的文档类型下验证,并且可以完全使用CSS进行样式化。

1
这仅适用于PHP,不适用于其他语言。 - Konrad Rudolph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接