Markdown.pl extending
Note that a substitution only occurs if there is a match, and then it will return the number of substitutions it makes. This means that a true value is returned if a match/substitution happens.

With that in mind, you don't need the m/.../ in addition to the substitution. You can also make use of or to achieve the short-circuiting that you had with the if ... elsif ... else ... statements.

foreach (@grafs) {
    unless (defined $g_html_blocks{$_}) {
        $_ = _RunSpanGamut($_);
        s/^([ \t]*\?[ \t]*)/&lt;p class="Introduction"&gt;/
            or
        s/^([ \t]*\![ \t]*)/&lt;p class="Important"&gt;/ 
            or
        s/^([ \t]*%[ \t]*)/&lt;p style="clear: both;"&gt;/
            or
        s/^([ \t]*)/&lt;p&gt;/;
        $_ .= "&lt;/p&gt;";
    }
}


For the image floating, you could use a hash instead of if ... else ...:

my %float = (
    '&lt;' =&gt; 'float: left',
    '&gt;' =&gt; 'float: right',
    '%' =&gt; 'clear: both'
);
if (defined $align) {
    $result .= " style=\"$float{$align}; margin: 0 ${padding}px ${padding}px 0;\"";
}


A minor point: I also removed the parens from the defined checks because they're not needed and it gives you a little more white space to reduce a little clutter.