在HTML中显示美观的Perl代码而不使用JavaScript

您想在网页上显示美观的语法高亮Perl代码,而不使用JavaScript吗?也许您想使用现有的CSS主题,而不必在Perl代码中编写内联CSS?如果是这样,请看看PPI::Prettify

背景

prettify.js库在为网页显示代码时,对大量不同的语言进行语法着色做得非常出色。它被用于blogs.perl.org;我们在PerlTricks.com上使用它。但由于Perl是一种模糊的语言,prettify.js通常无法正确标记所有代码。更糟糕的是,如果用户禁用了JavaScript,代码将根本不会高亮显示。这就是我编写PPI::Prettify的原因。它使用PPI::Document在后台运行,因此比prettify.js更快更准确,但输出的HTML代码与prettify.js相同,这使得您可以使用任何现有的CSS主题(例如这里这里这里)。

需求

您将需要PPI::Prettify,并且可以在终端通过CPAN安装它。

$ cpan PPI::Prettify

在操作系统兼容性方面,PPI::Prettify是纯Perl编写的,因此您应该在安装了Perl的任何平台上运行它。

标记内联Perl代码

PPI::Prettify导出了一个prettify()方法,它接受一个Perl代码字符串,并返回用标签标记的标记化代码。为了安全起见,PPI::Prettify对所有标记内容进行HTML编码。让我们快速编写一个脚本以演示prettify()。

use warnings;
use strict;
use PPI::Prettify;

read(main::DATA, my $code, 500);

print prettify({ code => $code });

__DATA__
# a simple OO class

package Shape;

sub new {
    my ($class, $args) = @_;
    my $self = {
        color  => $args->{color} || 'black',
        length => $args->{length} || 1,
        width  => $args->{width} || 1,
    };
    return bless $self, $class;
}

sub get_area {
    my $self = shift;
    return $self->{length} * $self->{width};
}

sub get_color {
    my $self = shift;
    return $self->{color};
}

sub set_color {
    my ($self, $color) = @_;
    $self->{color} = $color;
}

1;

该脚本使用__DATA__标记来创建一个文件句柄以指向一些内联Perl代码(该代码是从我们文章Old School Object Oriented Perl中取出的简单面向对象示例)。读取函数将文件句柄内容吸入$code。然后我们使用prettify()函数标记和标记Perl代码。

运行该脚本将返回用标签包围的Perl代码。这是prettify()产生的标记的总结。

<pre class="prettyprint"><span class="com"># a simple OO class
</span><span class="pln">
</span><span class="kwd">package</span><span class="pln"> </span><span class="atn">Shape</span><span class="pln">;</span>
...
</pre>

下面的示例显示了使用desert CSS主题时标记的外观。

# a simple OO class

package Shape;

sub new {
    my ($class, $args) = @_;
    my $self = {
        color  => $args->{color} || 'black',
        length => $args->{length} || 1,
        width  => $args->{width} || 1,
    };
    return bless $self, $class;
}

sub get_area {
    my $self = shift;
    return $self->{length} * $self->{width};
}

sub get_color {
    my $self = shift;
    return $self->{color};
}

sub set_color {
    my ($self, $color) = @_;
    $self->{color} = $color;
}

1;

这里有两点需要注意:禁用JavaScript不会影响上面的语法高亮,因为它是在后台使用PPI::Prettify生成的。其次,代码正确显示了多行注释(从__DATA__之后的内容),这与prettify.js不同。

标记存储在文件中的Perl代码

很容易从文件中美化现有的Perl代码。您可以在终端用一行Perl完成此操作。

$ perl -MPPI::Prettify -MFile::Slurp -e '$code=read_file("output");print prettify({code=>$code})'

高级功能1:调试模式

prettify()方法还接受一个可选的调试参数。

my $html = prettify({ code => $code, debug => 1 });

调试模式将提供相同的输出,但是每个标签都将有一个“title”属性,其值是原始PPI::Token类。这可以帮助您通过将光标悬停在文本上理解原始PPI::Token类如何映射到标记。以下是启用调试模式打印的代码。试试悬停!

# a simple OO class

package Shape;

sub new {
    my ($class, $args) = @_;
    my $self = {
        color  => $args->{color} || 'black',
        length => $args->{length} || 1,
        width  => $args->{width} || 1,
    };
    return bless $self, $class;
}

sub get_area {
    my $self = shift;
    return $self->{length} * $self->{width};
}

sub get_color {
    my $self = shift;
    return $self->{color};
}

sub set_color {
    my ($self, $color) = @_;
    $self->{color} = $color;
}

1;

高级功能2:覆盖映射

您可能希望更改Perl代码中某些标记的token。PPI::Prettify导出映射到名为$MARKUP_RULES的哈希引用中。每个PPI::Token类都是键,其值是prettify.js使用的CSS类名(以及prettify CSS主题预期的)。例如,PPI::Token::Comment映射到“com”

'PPI::Token::Comment' => 'com'

结合调试模式,应可直接更改特定PPI::Token类到所需prettify类的映射。

替代方案

如果您愿意在Perl代码中编写内联CSS,或者需要比PPI::Prettify提供的约10个类更详细的标记,请考虑使用Adam Kennedy的PPI::HTML。这是一个更成熟的模块,还可以进行行编号。


本文最初发布在PerlTricks.com

标签

David Farrell

David是一位专业程序员,他经常推文博客关于代码和编程艺术。

浏览他们的文章

反馈

这篇文章有什么问题吗?请在GitHub上打开一个问题或拉取请求,帮助我们。