hacksaw plugin - displaying first 100 characters
In my opinion, the first thing you should do is remove all HTML tags. It's not just paragraph tags which could cause you problems... what about &lt;strong&gt;, &lt;a&gt; or &lt;img&gt; tags which get cut off?

For legibility sake, let's also break this down into multiple steps:

{% set textBlock = entry.bodyContent.type('text').first() %}
{% set plainText = textBlock.text|striptags %}
{% set sumtext   = plainText|hacksaw(chars='100', append='...') %}


And finally, if you do want your text wrapped in a paragraph tag, just reapply that when you output it:

&lt;p&gt;{{ sumtext }}&lt;/p&gt;


Since you mentioned having an issue with two paragraphs getting mushed together, let me address that too... You'll want to make use of the Craft replace filter, which can handle regex.

Couple of ways you could tackle that:


{% set plainText = plainText|replace('/\. */', '. ') %} (ensures periods are followed by a single space)
{% set textBlock = textBlock|replace('/&lt;\/p&gt; *&lt;p&gt;/', ' ') %} (gracefully combines paragraphs with a space in between)