将HTML有序和无序列表转换为kramdown

时间:2016-04-18 18:44:14

标签: perl kramdown

是否可以使用Perl脚本将HTML有序和无序列表转换为kramdown,如果该文件可能包含多种类型的列表,以及其他HTML代码?

为了说明意图,如果只有一个有序列表而没有其他列表,那么类似下面的内容可能会有效:

$content =~ s!<\/ol>!!gis;
$content =~ s!<ol>!!gis;
$content =~ s!<\/li>!!gis;
$content =~ s!<li>!1. !gis;

如果只有一个无序列表而没有其他列表,那么这可能有效:

$content =~ s!<\/ol>!!gis;
$content =~ s!<ol>!!gis;
$content =~ s!<\/li>!!gis;
$content =~ s!<li>!- !gis;

例如,是否可以在HTML文档中找到每个列表,并将其传递给子例程,该子例程将确定列表的类型,将其适当转换并返回?

2 个答案:

答案 0 :(得分:2)

最简单的方法是使用kramdown本身,因为它可以解析HTML并发出一个kramdown文档。

使用kramdown二进制文件只需使用kramdown -i html -o kramdown INPUT.HTML

答案 1 :(得分:0)

通常,您不应使用正则表达式来解析HTML。相反,您应该使用像Mojo::DOM这样的HTML解析器:

use strict;
use warnings 'all';

use Mojo::DOM;

# Add the appropriate kramdown list marker to a Mojo::DOM node representing a
# single <li>, depending on whether it's in an <ol> or <ul>
sub add_list_marker {
    my ($node, $i) = @_;

    my $marker = $node->parent->tag eq 'ol' ? "$i. " : '- ';
    $node->prepend_content($marker);
}

# Convert a Mojo::DOM node representing an <ol> or <ul> to the corresponding
# kramdown
sub list_to_kramdown {
    my ($node) = @_;

    my $items = $node->children('li')->each(\&add_list_marker);
    my $text = $items->map('text')->join("\n");

    $node->replace("\n$text\n");
}

my $html = do {
    local $/;
    <DATA>
};

my $dom = Mojo::DOM->new($html);
$dom->find('ol, ul')->each(\&list_to_kramdown);
print $dom->to_string;

__DATA__
<h1>Leave surrounding HTML</h1>
<div id="including_enclosing_tags">
  <ol>
    <li>foo</li>
    <li>bar</li><li>baz</li>
    <li>qux</li>
  </ol>
  <ul>
    <li class="fruit">apple</li>
    <li>pear</li>
    <li>banana</li>
    <li>pine
        apple</li>
  </ul>
</div>

输出:

<h1>Leave surrounding HTML</h1>
<div id="including_enclosing_tags">

1. foo
2. bar
3. baz
4. qux


- apple
- pear
- banana
- pine apple

</div>

这比正则表达式更好,因为它可以轻松处理:

  • 同一行上的多个<li>元素
  • <li>元素跨越多行
  • 具有属性的元素