basic shortcode – Why 1st paragraph not wrapped in p tag, but 2nd is

This is actually an example of the wpautop() function‘s intended purpose. From the Codex:

Changes double line-breaks in the text into HTML paragraphs (<p></p>).

Note that the example provided in the Codex explicitly uses a string that begins with a line-break for this very purpose:

<?php
$some_long_text = // Start Text
Some long text
that has many lines

and paragraphs in it.
// end text

echo wpautop($some_long_text);
?>

The above results in following markup:

<p>Some long text<br/>
that has many lines</p>
<p>and paragraphs in it.</p>

The reasoning behind this functionality is that double line-breaks in HTML markup are interpreted as generic whitespace and render as a single line-break in the DOM. In order to properly display a double line-break, you either have to insert <br /> elements or make use of default paragraph-element styling, which is what WordPress does.

As the first line of your example contains no line-breaks, no paragraph or <br /> elements are added, as no line-break formatting needs to be preserved.

See the wpautop() function’s source for the exact implementation.

tech