diff --git a/HTMLKit/HTMLNode.m b/HTMLKit/HTMLNode.m
index be7a196..f2751e9 100644
--- a/HTMLKit/HTMLNode.m
+++ b/HTMLKit/HTMLNode.m
@@ -319,18 +319,18 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
void (^ hierarchyError)() = ^{
[NSException raise:HTMLKitHierarchyRequestError
- format:@"%@: Hierarchy Request Error. The operation would yield an incorrect node tree.",
- NSStringFromSelector(_cmd)];
+ format:@"%@: Hierarchy Request Error, inserting (%@) into (%@). The operation would yield an incorrect node tree.",
+ NSStringFromSelector(_cmd), self, node];
};
if (self.type == HTMLNodeDocument) {
switch (node.type) {
case HTMLNodeDocumentFragment:
- if (self.childNodesCount > 1 ||
- [self hasChildNodeOfType:HTMLNodeText]) {
+ if (node.childNodesCount > 1 ||
+ [node hasChildNodeOfType:HTMLNodeText]) {
hierarchyError();
- } else if (self.childNodesCount == 1) {
- if (self.hasChildNodes ||
+ } else if (node.childNodesCount == 1) {
+ if ([self hasChildNodeOfType:HTMLNodeElement] ||
child.type == HTMLNodeDocumentType ||
child.nextSibling.type == HTMLNodeDocumentType) {
hierarchyError();
diff --git a/HTMLKitTests/HTMLKitNodesTests.m b/HTMLKitTests/HTMLKitNodesTests.m
index a38959d..9c2dccc 100644
--- a/HTMLKitTests/HTMLKitNodesTests.m
+++ b/HTMLKitTests/HTMLKitNodesTests.m
@@ -537,4 +537,41 @@
XCTAssertNoThrow([[HTMLTemplate new] appendNode:text]);
}
+- (void)testValidDocumentFragmentInsertionIntoDocument
+{
+ HTMLDocument *document = [HTMLDocument new];
+ HTMLDocumentFragment *fragment = [[HTMLDocumentFragment alloc] initWithDocument:document];
+
+ void (^ reset)() = ^ {
+ [fragment removeAllChildNodes];
+ [document removeAllChildNodes];
+ };
+
+ [fragment appendNode:[HTMLText new]];
+ XCTAssertThrows([document appendNode:fragment]);
+
+ reset();
+ [fragment appendNode:[HTMLElement new]];
+ [fragment appendNode:[HTMLElement new]];
+ XCTAssertThrows([document appendNode:fragment]);
+
+ reset();
+ [fragment appendNode:[HTMLElement new]];
+ [document appendNode:[HTMLElement new]];
+ XCTAssertThrows([document appendNode:fragment]);
+
+ reset();
+ HTMLDocumentType *doctype = [HTMLDocumentType new];
+ [fragment appendNode:[HTMLElement new]];
+ [document appendNode:doctype];
+ XCTAssertThrows([document insertNode:fragment beforeChildNode:doctype]);
+
+ reset();
+ HTMLComment *doctypePreviousSibling = [HTMLComment new];
+ [fragment appendNode:[HTMLElement new]];
+ [document appendNode:doctypePreviousSibling];
+ [document appendNode:doctype];
+ XCTAssertThrows([document insertNode:fragment beforeChildNode:doctypePreviousSibling]);
+}
+
@end