Enclose paragraphs separated by blank lines; place <br /> before single newlines. Be smart about block elements like <blockquote>, e.g.:

I quote Lord Pilaf:

<blockquote>
Blah blah blah.

Blah!
</blockquote>

becomes

<p>I quote Lord Pilaf:</p>

<blockquote>
<p>Blah blah blah.</p>

<p>Blah!</p>
</blockquote>

my %is_approved_element = map { $_ => 1 } qw(a b big blockquote br cen +ter cite code dd div dl dt em font hr i img i ol p pre samp small span strong sub sup table td th tr tt u ul); my %is_block_element = map { $_ => 1 } qw(blockquote center div dl ol +pre table ul); my %is_raw_element = map { $_ => 1 } qw(dl ol pre table ul); my %is_empty_element = map { $_ => 1} qw(br img hr); sub render_text { my $str = shift; my $no_margin = shift; my $buf; my @tag_stack; my $raw; my $nl; my $in_p; $str =~ s/&(?!\#?[a-zA-Z0-9]+;)/&amp;/g; $str =~ s{<person>([^<>]+)</person>} {sprintf(qq|<a href="%s?%s">% +s</a>|, $script_name, user_id($1), $1)}gei; while ($str) { my $out; my $need_p = !$in_p && !$raw; if ($str =~ s/^([^<>\n]+)//) { $out = $1; for ($out) { my $in_a = grep { $_ eq 'a' } @tag_stack; unless ($in_a) { s{((?:http|https|ftp|mailto):\S+[a-zA-Z0-9/])} {<a href="$ +1">$1</a>}g; } } } elsif ($str =~ s/^<//) { if ($str =~ s/^(\/?)([a-zA-Z][a-zA-Z0-9\.-]*)(.*?)>//) { my $close = $1; my $name = lc $2; my $attributes = $3; if ($is_approved_element{$name}) { if ($is_block_element{$name}) { # A <p> tag produced by \n\n should go after a <blockquote +> tag, # not before it. $need_p = 0; if ($close && $in_p) { $buf .= '</p>'; $in_p = 0; } if ($is_raw_element{$name}) { if ($close) { $raw--; } else { $raw++; } } } if ($close) { # Catch a pending \n so it doesn't get translated to <br / +>. if ($nl) { $out .= "\n"; $nl = 0; } if ($tag_stack[0] eq $name) { $out .= "</$name>"; shift(@tag_stack); } } else { $out .= "<$name$attributes>"; unless ($is_empty_element{$name}) { unshift(@tag_stack, $name); $str =~ s/^(\n+)//; $out .= $1; } } } else { $out = "&lt;$close$name$attributes&gt;"; } } else { $out = '&lt;'; } } elsif ($str =~ s/^>//) { $out = '&gt;'; } elsif ($str =~ s/^(\n{2,})//) { if ($in_p) { $buf .= '</p>'; $in_p = 0; } $buf .= $1; } elsif ($str =~ s/^\n//) { if ($raw) { $buf .= "\n"; } else { $nl = 1; } } if ($out) { if ($nl) { $buf .= "<br />\n"; $nl = 0; } if ($need_p) { $buf .= '<p>'; $in_p = 1; } $buf .= $out; } } for my $name (@tag_stack) { $buf .= "</$name>"; } if ($in_p) { $buf .= '</p>'; } if ($no_margin) { my $first_p = index($buf, '<p>'); my $last_p = rindex($buf, '<p>'); if ($first_p == $last_p) { substr($buf, $first_p + 2, 0) = q| style="margin: 0"|; } else { if ($last_p >= 0) { substr($buf, $last_p + 2, 0) = q| style="margin-bottom: 0"|; } if ($first_p >= 0) { substr($buf, $first_p + 2, 0) = q| style="margin-top: 0"|; } } } return $buf; }

In reply to Text to XHTML by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.