parsedown-extra icon indicating copy to clipboard operation
parsedown-extra copied to clipboard

HTML on one line renders incorrectly

Open jasonvarga opened this issue 9 years ago • 15 comments

If you have HTML on a single line, only the first will render.

See this screenshot of the behavior from the demo.

Only happens in Parsedown Extra. Regular Parsedown is fine.

jasonvarga avatar Feb 05 '15 00:02 jasonvarga

Also occurs when there is nbsp (u+a0) at the end of the line.

<div></div> 

Google is eaten

It seems only block elements do this. Inline elems are unaffected. Only Parsedown Extra is affected.

jtojnar avatar Feb 17 '15 15:02 jtojnar

I can confirm that this is a serious issue. What makes this a particularly nasty bug is that it results in a complete loss of the data as it was originally intended.

2015-03-14_19-04-00

<div>1</div><p>2</p>
The p tag (and contents), along with this line are eaten.

jaswrks avatar Mar 15 '15 03:03 jaswrks

I left a small donation hoping that it helps others resolve this.

jaswrks avatar Mar 15 '15 03:03 jaswrks

I'll see what I can do. It might take some time, though. I'll be quite busy over the next couple of weeks.

erusev avatar Mar 15 '15 03:03 erusev

It might take some time, though.

Copy that :-) I'm a veteran with PHP, but new to Parsedown. Any ideas where I might start debugging this? If so I might be able to submit a PR for this.

jaswrks avatar Mar 15 '15 03:03 jaswrks

Sure,

It's in the blockMarkup methods in Parsedown.php.

Parsedown does supports one line block-level elements, but it looks for a closing tag at the end of the line. It doesn't consider the element closed when it doesn't find a closing tag at the end of the line.

You could give it a shot, but it might take me much less time to fix. Unless it's urgent, it might make more sense to wait.

erusev avatar Mar 15 '15 03:03 erusev

@erusev writes...

blockMarkup methods in Parsedown.php

Thank you :-) I'll take a look at this in the next day or so and see what I can make of it. Otherwise, I'll wait patiently as suggested.

jaswrks avatar Mar 15 '15 10:03 jaswrks

I noticed an issue with a self closing element which ended in an endless loop. If an element doesn't have any children, the html should be appended directly and not through processText().

I've fixed this in: https://github.com/storeman/parsedown-extra/commit/ddd0d0bad88429fa8d3e372615b239d78bfd3f42

storeman avatar May 27 '15 21:05 storeman

@storeman Can you provide an example that I can use to reproduce the issue?

erusev avatar May 27 '15 21:05 erusev

First,I have to say it only occurs in the fix from @acmitch. The block element problem seems to be resolved.

Just process '' gave me this issue. I wanted to notify you about this, in case you wanted to merge the fix from @acmitch.

storeman avatar May 27 '15 21:05 storeman

@storeman Ah, I see, thanks, I appreciate it.

erusev avatar May 27 '15 22:05 erusev

Had more issues today with the solution from @acmitch. I deleted my fork because i could not find the clear edge case where his solution was breaking my html. One of the issues was, textareas were replicated and the dom-structure was altered. For example:

<textarea></textarea>
<label><input type="checkbox"> <a href="#">Some test</a></label>

Became

<textarea><textarea></textarea></textarea>
<label><input type="checkbox"></label> <a href="#">Some test</a>

It was caused by the surrounding html, but those 13000 lines were to hard to walk through.

storeman avatar May 28 '15 09:05 storeman

@storeman thanks for the feedback! Found a few issues related to the code block you provided.

<textarea></textarea>
<label><input type="checkbox"> <a href="#">Some test</a></label>

The first issue, as you mentioned above, was that specific elements were causing endless loops. This has been fixed in my latest commit acmitch@468ecc6

It is important to note that all inline or voided HTML elements must be within the $this->textLevelElements and $this->voidElements arrays located within the parsedown library for my fix to work properly.

Therefore, to fix the textarea issue you must add the textarea value to the $this->voidElements array, like such:

 protected $voidElements = array(
    'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'textarea'
 );

Once, that has been added you should be good to go (I've already tested and works like a charm)! Maybe @erusev can add the textarea permanently if he gets a chance. FYI: I plan to do a little more work to this library over the next few months. I can't seem to get the script tags working as well as a few small things. I will likely have to change the saveXML back to saveHTML once my PHP is updated to a newer version. You might even want to make that change if your PHP version is 5.3.6 or greater.

acmitch avatar May 28 '15 15:05 acmitch

Here is a failing testcase if it would be of help:

public function testStripping()
{
    $expectedMarkup = '<p><strong>Contact Method:</strong> email</p><p>Test</p><p><em>Some italic text.</em></p>';
    $actualMarkup = (new ParsedownExtra())->text($expectedMarkup);

    $this->assertEquals($expectedMarkup, $actualMarkup);
}

Results:

1) ParsedownExtraTest::testStripping
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'<p><strong>Contact Method:</strong> email</p><p>Test</p><p><em>Some italic text.</em></p>'
+'<p><strong>Contact Method:</strong> email</p>'

ericlbarnes avatar Nov 25 '15 16:11 ericlbarnes

@ericbarnes Thanks, Eric, I appreciate it, hopefully, I'll have some time later this month to address the issue.

erusev avatar Nov 25 '15 16:11 erusev