mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-08-05 13:47:24 +02:00
Improve auto-paragraph to preserve newlines and handle edge-cases better.
This is a very large commit that includes numerous improvements to the AutoParagraph injector. These are: * Rewritten flow control of the injector to use almost exclusively binary conditionals. * Improved inline documentation with "State" comments, which give concise examples of what the token stack looks like at flow points. * Documentation for all flow branches, even those with no actions. * Factoring out of common operations to improve readability, especially the new iterator private methods. * Expanded test-suite which covers new flow points, and corrects some errors in previous cases. Signed-off-by: Edward Z. Yang <edwardzyang@thewritingpot.com>
This commit is contained in:
@@ -35,16 +35,6 @@ class HTMLPurifier_ComplexHarness extends HTMLPurifier_Harness
|
||||
*/
|
||||
protected $lexer;
|
||||
|
||||
/**
|
||||
* Default config to fall back on if no config is available
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Default context to fall back on if no context is available
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
public function __construct() {
|
||||
$this->lexer = new HTMLPurifier_Lexer_DirectLex();
|
||||
parent::__construct();
|
||||
@@ -88,7 +78,6 @@ class HTMLPurifier_ComplexHarness extends HTMLPurifier_Harness
|
||||
$expect = $this->generate($expect);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertIdentical($expect, $result);
|
||||
|
||||
}
|
||||
|
@@ -29,7 +29,9 @@ Par 1 still</p>'
|
||||
'Par1
|
||||
|
||||
Par2',
|
||||
'<p>Par1</p><p>Par2</p>'
|
||||
"<p>Par1</p>
|
||||
|
||||
<p>Par2</p>"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +42,9 @@ Par2',
|
||||
|
||||
|
||||
Par2',
|
||||
'<p>Par1</p><p>Par2</p>'
|
||||
'<p>Par1</p>
|
||||
|
||||
<p>Par2</p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,7 +53,9 @@ Par2',
|
||||
'<b>Par1</b>
|
||||
|
||||
<i>Par2</i>',
|
||||
'<p><b>Par1</b></p><p><i>Par2</i></p>'
|
||||
'<p><b>Par1</b></p>
|
||||
|
||||
<p><i>Par2</i></p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,7 +73,9 @@ Par2</b></p>'
|
||||
function testAddParagraphAdjacentToParagraph() {
|
||||
$this->assertResult(
|
||||
'Par1<p>Par2</p>',
|
||||
'<p>Par1</p><p>Par2</p>'
|
||||
'<p>Par1</p>
|
||||
|
||||
<p>Par2</p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,7 +99,9 @@ Par1</pre>'
|
||||
'Par1
|
||||
|
||||
',
|
||||
'<p>Par1</p>'
|
||||
'<p>Par1</p>
|
||||
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -102,7 +112,11 @@ Par1</pre>'
|
||||
<div>Par2</div>
|
||||
|
||||
Par3',
|
||||
'<p>Par1</p><div>Par2</div><p>Par3</p>'
|
||||
'<p>Par1</p>
|
||||
|
||||
<div>Par2</div>
|
||||
|
||||
<p>Par3</p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,23 +127,29 @@ Par3',
|
||||
);
|
||||
}
|
||||
|
||||
function testIgnoreLeadingWhitespace() {
|
||||
function testPreserveLeadingWhitespace() {
|
||||
$this->assertResult(
|
||||
'
|
||||
|
||||
Par',
|
||||
'<p>Par</p>'
|
||||
'
|
||||
|
||||
<p>Par</p>'
|
||||
);
|
||||
}
|
||||
|
||||
function testIgnoreSurroundingWhitespace() {
|
||||
function testPreserveSurroundingWhitespace() {
|
||||
$this->assertResult(
|
||||
'
|
||||
|
||||
Par
|
||||
|
||||
',
|
||||
'<p>Par</p>'
|
||||
'
|
||||
|
||||
<p>Par</p>
|
||||
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -138,7 +158,9 @@ Par
|
||||
'<div>Par1
|
||||
|
||||
Par2</div>',
|
||||
'<div><p>Par1</p><p>Par2</p></div>'
|
||||
'<div><p>Par1</p>
|
||||
|
||||
<p>Par2</p></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,7 +169,9 @@ Par2</div>',
|
||||
'<div><b>Par1</b>
|
||||
|
||||
Par2</div>',
|
||||
'<div><p><b>Par1</b></p><p>Par2</p></div>'
|
||||
'<div><p><b>Par1</b></p>
|
||||
|
||||
<p>Par2</p></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -160,7 +184,9 @@ Par2</div>',
|
||||
'<div><b>Par1</b>
|
||||
|
||||
<i>Par2</i></div>',
|
||||
'<div><p><b>Par1</b></p><p><i>Par2</i></p></div>'
|
||||
'<div><p><b>Par1</b></p>
|
||||
|
||||
<p><i>Par2</i></p></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -177,7 +203,9 @@ Par2</div>',
|
||||
'<div><p>Foo
|
||||
|
||||
Bar</p></div>',
|
||||
'<div><p>Foo</p><p>Bar</p></div>'
|
||||
'<div><p>Foo</p>
|
||||
|
||||
<p>Bar</p></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -186,7 +214,9 @@ Bar</p></div>',
|
||||
'<div><p><b>Foo</b>
|
||||
|
||||
<i>Bar</i></p></div>',
|
||||
'<div><p><b>Foo</b></p><p><i>Bar</i></p></div>'
|
||||
'<div><p><b>Foo</b></p>
|
||||
|
||||
<p><i>Bar</i></p></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -199,7 +229,9 @@ Bar</p></div>',
|
||||
'<blockquote>Par1
|
||||
|
||||
Par2</blockquote>',
|
||||
'<blockquote><p>Par1</p><p>Par2</p></blockquote>'
|
||||
'<blockquote><p>Par1</p>
|
||||
|
||||
<p>Par2</p></blockquote>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -218,7 +250,11 @@ Par2</blockquote>',
|
||||
Bar
|
||||
|
||||
</div>',
|
||||
'<div><p>Bar</p></div>'
|
||||
'<div>
|
||||
|
||||
<p>Bar</p>
|
||||
|
||||
</div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -229,7 +265,9 @@ Bar
|
||||
|
||||
|
||||
Par2',
|
||||
'<p><b>Par1</b>a</p><p>Par2</p>'
|
||||
'<p><b>Par1</b>a</p>
|
||||
|
||||
<p>Par2</p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -238,7 +276,9 @@ Par2',
|
||||
'Par1
|
||||
|
||||
Par2</p>',
|
||||
'<p>Par1</p><p>Par2</p>'
|
||||
'<p>Par1</p>
|
||||
|
||||
<p>Par2</p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -247,7 +287,9 @@ Par2</p>',
|
||||
'Par1
|
||||
|
||||
Par2</div>',
|
||||
'<p>Par1</p><p>Par2</p>'
|
||||
'<p>Par1</p>
|
||||
|
||||
<p>Par2</p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -264,7 +306,9 @@ Par1
|
||||
'<div>Par1
|
||||
|
||||
<div>Par2</div></div>',
|
||||
'<div><p>Par1</p><div>Par2</div></div>'
|
||||
'<div><p>Par1</p>
|
||||
|
||||
<div>Par2</div></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -280,7 +324,9 @@ Par1
|
||||
'Par1
|
||||
<div>Par2</div>',
|
||||
'<p>Par1
|
||||
</p><div>Par2</div>'
|
||||
</p>
|
||||
|
||||
<div>Par2</div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -289,7 +335,9 @@ Par1
|
||||
'Par1
|
||||
|
||||
<b>Par2</b>',
|
||||
'<p>Par1</p><p><b>Par2</b></p>'
|
||||
'<p>Par1</p>
|
||||
|
||||
<p><b>Par2</b></p>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -323,7 +371,9 @@ Par1
|
||||
'<div><div>asdf</div>
|
||||
|
||||
<b>asdf</b></div>',
|
||||
'<div><div>asdf</div><p><b>asdf</b></p></div>'
|
||||
'<div><div>asdf</div>
|
||||
|
||||
<p><b>asdf</b></p></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -354,7 +404,9 @@ Par2'
|
||||
'<div><code>bar</code> mmm
|
||||
|
||||
<pre>asdf</pre></div>',
|
||||
'<div><p><code>bar</code> mmm</p><pre>asdf</pre></div>'
|
||||
'<div><p><code>bar</code> mmm</p>
|
||||
|
||||
<pre>asdf</pre></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -363,7 +415,85 @@ Par2'
|
||||
'<div>asdf <code>bar</code> mmm
|
||||
|
||||
<pre>asdf</pre></div>',
|
||||
'<div><p>asdf <code>bar</code> mmm</p><pre>asdf</pre></div>'
|
||||
'<div><p>asdf <code>bar</code> mmm</p>
|
||||
|
||||
<pre>asdf</pre></div>'
|
||||
);
|
||||
}
|
||||
|
||||
function testUpcomingTokenHasNewline() {
|
||||
$this->assertResult(
|
||||
'<div>Test<b>foo</b>bar<b>bing</b>bang
|
||||
|
||||
boo</div>',
|
||||
'<div><p>Test<b>foo</b>bar<b>bing</b>bang</p>
|
||||
|
||||
<p>boo</p></div>'
|
||||
);
|
||||
}
|
||||
|
||||
function testEmptyTokenAtEndOfDiv() {
|
||||
$this->assertResult(
|
||||
'<div><p>foo</p>
|
||||
</div>',
|
||||
'<div><p>foo</p>
|
||||
</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function testEmptyDoubleLineTokenAtEndOfDiv() {
|
||||
$this->assertResult(
|
||||
'<div><p>foo</p>
|
||||
|
||||
</div>',
|
||||
'<div><p>foo</p>
|
||||
|
||||
</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function testTextState11Root() {
|
||||
$this->assertResult('<div></div> ');
|
||||
}
|
||||
|
||||
function testTextState11Element() {
|
||||
$this->assertResult(
|
||||
"<div><div></div>
|
||||
|
||||
</div>");
|
||||
}
|
||||
|
||||
function testTextStateLikeElementState111NoWhitespace() {
|
||||
$this->assertResult('<div><p>P</p>Boo</div>', '<div><p>P</p>Boo</div>');
|
||||
}
|
||||
|
||||
function testElementState111NoWhitespace() {
|
||||
$this->assertResult('<div><p>P</p><b>Boo</b></div>', '<div><p>P</p><b>Boo</b></div>');
|
||||
}
|
||||
|
||||
function testElementState133() {
|
||||
$this->assertResult(
|
||||
"<div><b>B</b><pre>Ba</pre>
|
||||
|
||||
Bar</div>",
|
||||
"<div><b>B</b><pre>Ba</pre>
|
||||
|
||||
<p>Bar</p></div>"
|
||||
);
|
||||
}
|
||||
|
||||
function testElementState22() {
|
||||
$this->assertResult(
|
||||
'<ul><li>foo</li></ul>'
|
||||
);
|
||||
}
|
||||
|
||||
function testElementState311() {
|
||||
$this->assertResult(
|
||||
'<p>Foo</p><b>Bar</b>',
|
||||
'<p>Foo</p>
|
||||
|
||||
<p><b>Bar</b></p>'
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -72,14 +72,18 @@ class HTMLPurifier_Strategy_MakeWellFormed_InjectorTest extends HTMLPurifier_Str
|
||||
function testTwoParagraphsContainingOnlyOneLink() {
|
||||
$this->assertResult(
|
||||
"http://example.com\n\nhttp://dev.example.com",
|
||||
'<p><a href="http://example.com">http://example.com</a></p><p><a href="http://dev.example.com">http://dev.example.com</a></p>'
|
||||
'<p><a href="http://example.com">http://example.com</a></p>
|
||||
|
||||
<p><a href="http://dev.example.com">http://dev.example.com</a></p>'
|
||||
);
|
||||
}
|
||||
|
||||
function testParagraphNextToDivWithLinks() {
|
||||
$this->assertResult(
|
||||
'http://example.com <div>http://example.com</div>',
|
||||
'<p><a href="http://example.com">http://example.com</a> </p><div><a href="http://example.com">http://example.com</a></div>'
|
||||
'<p><a href="http://example.com">http://example.com</a> </p>
|
||||
|
||||
<div><a href="http://example.com">http://example.com</a></div>'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -92,24 +96,50 @@ class HTMLPurifier_Strategy_MakeWellFormed_InjectorTest extends HTMLPurifier_Str
|
||||
|
||||
function testParagraphAfterLinkifiedURL() {
|
||||
$this->assertResult(
|
||||
"http://google.com\n\n<b>b</b>",
|
||||
"<p><a href=\"http://google.com\">http://google.com</a></p><p><b>b</b></p>"
|
||||
"http://google.com
|
||||
|
||||
<b>b</b>",
|
||||
"<p><a href=\"http://google.com\">http://google.com</a></p>
|
||||
|
||||
<p><b>b</b></p>"
|
||||
);
|
||||
}
|
||||
|
||||
function testEmptyAndParagraph() {
|
||||
// This is a fairly degenerate case, but it demonstrates that
|
||||
// the two don't error out together, at least.
|
||||
// Change this behavior!
|
||||
$this->assertResult(
|
||||
"<p>asdf\n\nasdf<b></b></p>\n\n<p></p><i></i>",
|
||||
"<p>asdf</p><p>asdf</p>"
|
||||
"<p>asdf
|
||||
|
||||
asdf<b></b></p>
|
||||
|
||||
<p></p><i></i>",
|
||||
"<p>asdf</p>
|
||||
|
||||
<p>asdf</p>
|
||||
|
||||
|
||||
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
function testRewindAndParagraph() {
|
||||
// perhaps change the behavior of this?
|
||||
$this->assertResult(
|
||||
"bar\n\n<p><i></i>\n\n</p>\n\nfoo",
|
||||
"<p>bar</p><p>foo</p>"
|
||||
"bar
|
||||
|
||||
<p><i></i>
|
||||
|
||||
</p>
|
||||
|
||||
foo",
|
||||
"<p>bar</p>
|
||||
|
||||
<p></p>
|
||||
|
||||
<p>foo</p>"
|
||||
);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user