Merge branch 'develop' into feature/css_selectors
Conflicts: HTMLKit.xcodeproj/project.pbxproj HTMLKit/HTMLNodeFilter.h
This commit is contained in:
@@ -53,14 +53,11 @@
|
||||
6238579B1A9E8934003A45D9 /* HTMLComment.h in Headers */ = {isa = PBXBuildFile; fileRef = 623857991A9E8934003A45D9 /* HTMLComment.h */; };
|
||||
6238579C1A9E8934003A45D9 /* HTMLComment.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238579A1A9E8934003A45D9 /* HTMLComment.m */; };
|
||||
6238579D1A9E8934003A45D9 /* HTMLComment.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238579A1A9E8934003A45D9 /* HTMLComment.m */; };
|
||||
6238C9851AB8D6330006512E /* HTMLKitExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238C9831AB8D6330006512E /* HTMLKitExceptions.h */; };
|
||||
6238C9861AB8D6330006512E /* HTMLKitExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitExceptions.m */; };
|
||||
6238C9871AB8D6330006512E /* HTMLKitExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitExceptions.m */; };
|
||||
623916C31AC707250066B4FE /* HTMLNodeTreeEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 623916C11AC707250066B4FE /* HTMLNodeTreeEnumerator.h */; };
|
||||
623916C41AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */; };
|
||||
623916C51AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */; };
|
||||
623916C71AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */; };
|
||||
623916C81AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */; };
|
||||
6238C9851AB8D6330006512E /* HTMLKitDOMExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */; };
|
||||
6238C9861AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */; };
|
||||
6238C9871AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */; };
|
||||
623916C71AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */; };
|
||||
623916C81AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */; };
|
||||
6239755A1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623975591AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m */; };
|
||||
6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 623975591AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m */; };
|
||||
6239755E1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */; };
|
||||
@@ -86,6 +83,20 @@
|
||||
624AB31F1B05373600F3830D /* CSSSimpleSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB31D1B05373600F3830D /* CSSSimpleSequence.m */; };
|
||||
624AB3201B05373600F3830D /* CSSSimpleSequence.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB31D1B05373600F3830D /* CSSSimpleSequence.m */; };
|
||||
624AB3221B053A5800F3830D /* CSSSimpleSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 624AB3211B053A5800F3830D /* CSSSimpleSelector.h */; };
|
||||
624717181B22333200C11912 /* HTMLNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = 624717161B22333200C11912 /* HTMLNodeTraversal.h */; };
|
||||
624717191B22333200C11912 /* HTMLNodeTraversal.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717171B22333200C11912 /* HTMLNodeTraversal.m */; };
|
||||
6247171A1B22333200C11912 /* HTMLNodeTraversal.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717171B22333200C11912 /* HTMLNodeTraversal.m */; };
|
||||
6247171C1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */; };
|
||||
6247171D1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */; };
|
||||
624717B81B21FE5400B38302 /* HTMLNodeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */; };
|
||||
624717B91B21FE5400B38302 /* HTMLNodeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */; };
|
||||
624717BC1B22009200B38302 /* HTMLTreeWalker.h in Headers */ = {isa = PBXBuildFile; fileRef = 624717BA1B22009200B38302 /* HTMLTreeWalker.h */; };
|
||||
624717BD1B22009200B38302 /* HTMLTreeWalker.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717BB1B22009200B38302 /* HTMLTreeWalker.m */; };
|
||||
624717BE1B22009200B38302 /* HTMLTreeWalker.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717BB1B22009200B38302 /* HTMLTreeWalker.m */; };
|
||||
6247A9431B152F4F00CCF25C /* HTMLNodeIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */; };
|
||||
6247A9441B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */; };
|
||||
6247A9451B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */; };
|
||||
6247A9471B152F8C00CCF25C /* HTMLNodeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */; };
|
||||
624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = 624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */; };
|
||||
624AC90119FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */; };
|
||||
624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */; };
|
||||
@@ -145,7 +156,7 @@
|
||||
62AE594B19F9948A0043F069 /* HTMLCharacterToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE594819F9948A0043F069 /* HTMLCharacterToken.m */; };
|
||||
62D8345919FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */; };
|
||||
62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */; };
|
||||
62D89DB01AE7080300B6243D /* HTMLNodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 62362A3F1A9FDE8A00301989 /* HTMLNodes.h */; };
|
||||
62D89DB01AE7080300B6243D /* HTMLDOM.h in Headers */ = {isa = PBXBuildFile; fileRef = 62362A3F1A9FDE8A00301989 /* HTMLDOM.h */; };
|
||||
62D89DB11AE7081600B6243D /* HTMLTokenizerStates.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */; };
|
||||
62D89DB21AE7081600B6243D /* HTMLTokenizerCharacters.h in Headers */ = {isa = PBXBuildFile; fileRef = 62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */; };
|
||||
62D89DB31AE7081600B6243D /* HTMLNamespaces.h in Headers */ = {isa = PBXBuildFile; fileRef = 628B7CE61A080E1000602C87 /* HTMLNamespaces.h */; };
|
||||
@@ -214,7 +225,7 @@
|
||||
6235CE9F1AA5170A0026937B /* HTMLMarker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLMarker.m; sourceTree = "<group>"; };
|
||||
62362A3A1A9FA70400301989 /* HTMLText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLText.h; sourceTree = "<group>"; };
|
||||
62362A3B1A9FA70400301989 /* HTMLText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLText.m; sourceTree = "<group>"; };
|
||||
62362A3F1A9FDE8A00301989 /* HTMLNodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLNodes.h; sourceTree = "<group>"; };
|
||||
62362A3F1A9FDE8A00301989 /* HTMLDOM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLDOM.h; sourceTree = "<group>"; };
|
||||
62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLListOfActiveFormattingElements.h; sourceTree = "<group>"; };
|
||||
62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLListOfActiveFormattingElements.m; sourceTree = "<group>"; };
|
||||
6236738D1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTokenizerPerformance.m; sourceTree = "<group>"; };
|
||||
@@ -227,11 +238,9 @@
|
||||
623857951A9E8606003A45D9 /* HTMLDocumentType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLDocumentType.m; sourceTree = "<group>"; };
|
||||
623857991A9E8934003A45D9 /* HTMLComment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLComment.h; sourceTree = "<group>"; };
|
||||
6238579A1A9E8934003A45D9 /* HTMLComment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLComment.m; sourceTree = "<group>"; };
|
||||
6238C9831AB8D6330006512E /* HTMLKitExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLKitExceptions.h; sourceTree = "<group>"; };
|
||||
6238C9841AB8D6330006512E /* HTMLKitExceptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitExceptions.m; sourceTree = "<group>"; };
|
||||
623916C11AC707250066B4FE /* HTMLNodeTreeEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeTreeEnumerator.h; sourceTree = "<group>"; };
|
||||
623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeTreeEnumerator.m; sourceTree = "<group>"; };
|
||||
623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodeTreeEnumratorTests.m; sourceTree = "<group>"; };
|
||||
6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLKitDOMExceptions.h; sourceTree = "<group>"; };
|
||||
6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitDOMExceptions.m; sourceTree = "<group>"; };
|
||||
623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodeIteratorTests.m; sourceTree = "<group>"; };
|
||||
623975591AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTreeConstructionTests.m; sourceTree = "<group>"; };
|
||||
6239755C1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5LibTreeConstructionTest.h; sourceTree = "<group>"; };
|
||||
6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTreeConstructionTest.m; sourceTree = "<group>"; };
|
||||
@@ -251,6 +260,15 @@
|
||||
624AB31C1B05373600F3830D /* CSSSimpleSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSimpleSequence.h; sourceTree = "<group>"; };
|
||||
624AB31D1B05373600F3830D /* CSSSimpleSequence.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSSimpleSequence.m; sourceTree = "<group>"; };
|
||||
624AB3211B053A5800F3830D /* CSSSimpleSelector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSSimpleSelector.h; sourceTree = "<group>"; };
|
||||
624717161B22333200C11912 /* HTMLNodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeTraversal.h; sourceTree = "<group>"; };
|
||||
624717171B22333200C11912 /* HTMLNodeTraversal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeTraversal.m; sourceTree = "<group>"; };
|
||||
6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTreeWalkerTests.m; sourceTree = "<group>"; };
|
||||
624717B71B21FE5400B38302 /* HTMLNodeFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeFilter.m; sourceTree = "<group>"; };
|
||||
624717BA1B22009200B38302 /* HTMLTreeWalker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTreeWalker.h; sourceTree = "<group>"; };
|
||||
624717BB1B22009200B38302 /* HTMLTreeWalker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTreeWalker.m; sourceTree = "<group>"; };
|
||||
6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeIterator.h; sourceTree = "<group>"; };
|
||||
6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeIterator.m; sourceTree = "<group>"; };
|
||||
6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeFilter.h; sourceTree = "<group>"; };
|
||||
624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokens.h; sourceTree = "<group>"; };
|
||||
624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTokenizerTests.m; sourceTree = "<group>"; };
|
||||
624AC90419FBFE8A00BD3C4A /* html5lib-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "html5lib-tests"; sourceTree = "<group>"; };
|
||||
@@ -380,32 +398,40 @@
|
||||
name = Tokenizer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
623719441AA1472B002E03C8 /* Nodes */ = {
|
||||
623719441AA1472B002E03C8 /* DOM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
624B28BB1B03DAB70048D328 /* HTMLNodeFilter.h */,
|
||||
623719431AA12EE8002E03C8 /* HTMLQuirksMode.h */,
|
||||
62362A3F1A9FDE8A00301989 /* HTMLNodes.h */,
|
||||
62362A3F1A9FDE8A00301989 /* HTMLDOM.h */,
|
||||
6234584C1A9D2FA4009BD491 /* HTMLNode.h */,
|
||||
6234584D1A9D2FA4009BD491 /* HTMLNode.m */,
|
||||
6279F87219E1808D00F12EE5 /* HTMLElement.h */,
|
||||
6279F87319E1808D00F12EE5 /* HTMLElement.m */,
|
||||
6238578F1A9E772B003A45D9 /* HTMLDocument.h */,
|
||||
623857901A9E772B003A45D9 /* HTMLDocument.m */,
|
||||
623857941A9E8606003A45D9 /* HTMLDocumentType.h */,
|
||||
623857951A9E8606003A45D9 /* HTMLDocumentType.m */,
|
||||
623406E41ADB05AD004677A3 /* HTMLDocumentFragment.h */,
|
||||
623406E51ADB05AD004677A3 /* HTMLDocumentFragment.m */,
|
||||
6279F87219E1808D00F12EE5 /* HTMLElement.h */,
|
||||
6279F87319E1808D00F12EE5 /* HTMLElement.m */,
|
||||
623857991A9E8934003A45D9 /* HTMLComment.h */,
|
||||
6238579A1A9E8934003A45D9 /* HTMLComment.m */,
|
||||
62362A3A1A9FA70400301989 /* HTMLText.h */,
|
||||
62362A3B1A9FA70400301989 /* HTMLText.m */,
|
||||
623406DF1ADB04F9004677A3 /* HTMLTemplate.h */,
|
||||
623406E01ADB04F9004677A3 /* HTMLTemplate.m */,
|
||||
623406E41ADB05AD004677A3 /* HTMLDocumentFragment.h */,
|
||||
623406E51ADB05AD004677A3 /* HTMLDocumentFragment.m */,
|
||||
623916C11AC707250066B4FE /* HTMLNodeTreeEnumerator.h */,
|
||||
623916C21AC707250066B4FE /* HTMLNodeTreeEnumerator.m */,
|
||||
6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */,
|
||||
6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */,
|
||||
624717BA1B22009200B38302 /* HTMLTreeWalker.h */,
|
||||
624717BB1B22009200B38302 /* HTMLTreeWalker.m */,
|
||||
624717161B22333200C11912 /* HTMLNodeTraversal.h */,
|
||||
624717171B22333200C11912 /* HTMLNodeTraversal.m */,
|
||||
6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */,
|
||||
624717B71B21FE5400B38302 /* HTMLNodeFilter.m */,
|
||||
6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */,
|
||||
6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */,
|
||||
628B7CE61A080E1000602C87 /* HTMLNamespaces.h */,
|
||||
623719431AA12EE8002E03C8 /* HTMLQuirksMode.h */,
|
||||
);
|
||||
name = Nodes;
|
||||
name = DOM;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
623975581AC362A5007E26F1 /* Tree Construction */ = {
|
||||
@@ -419,15 +445,15 @@
|
||||
name = "Tree Construction";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
624B9FB71AE072CB00646C4C /* Nodes */ = {
|
||||
624B9FB71AE072CB00646C4C /* DOM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
623916C61AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m */,
|
||||
624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */,
|
||||
623916C61AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m */,
|
||||
6247171B1B2240B800C11912 /* HTMLTreeWalkerTests.m */,
|
||||
624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */,
|
||||
62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */,
|
||||
);
|
||||
name = Nodes;
|
||||
name = DOM;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
624B9FB81AE072D500646C4C /* Categories */ = {
|
||||
@@ -438,6 +464,14 @@
|
||||
name = Categories;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
624E1A2D1B1D1C8A00E66AAC /* Structures */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */,
|
||||
);
|
||||
name = Structures;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
625A14A219C7829400AD0C32 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -485,11 +519,9 @@
|
||||
children = (
|
||||
625A14BC19C7829400AD0C32 /* HTMLKit.h */,
|
||||
625A14BD19C7829400AD0C32 /* HTMLKit.m */,
|
||||
6238C9831AB8D6330006512E /* HTMLKitExceptions.h */,
|
||||
6238C9841AB8D6330006512E /* HTMLKitExceptions.m */,
|
||||
62AE593219F97CCA0043F069 /* Tokenizing */,
|
||||
628E16EC1ADAE71700B15A06 /* Parsing */,
|
||||
623719441AA1472B002E03C8 /* Nodes */,
|
||||
623719441AA1472B002E03C8 /* DOM */,
|
||||
628E16ED1ADAE73700B15A06 /* Categories */,
|
||||
628E16EE1ADAE75300B15A06 /* Structures */,
|
||||
62079BE61AF5656600D3B402 /* Selectors */,
|
||||
@@ -514,8 +546,9 @@
|
||||
children = (
|
||||
6236738C1AC0CD2400FF89B3 /* Tokenizer */,
|
||||
623975581AC362A5007E26F1 /* Tree Construction */,
|
||||
624B9FB71AE072CB00646C4C /* Nodes */,
|
||||
624B9FB71AE072CB00646C4C /* DOM */,
|
||||
624B9FB81AE072D500646C4C /* Categories */,
|
||||
624E1A2D1B1D1C8A00E66AAC /* Structures */,
|
||||
625A14CB19C7829400AD0C32 /* Supporting Files */,
|
||||
624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */,
|
||||
624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */,
|
||||
@@ -544,7 +577,6 @@
|
||||
6234BEED1AABBF1400DEB15F /* HTMLStackOfOpenElements.m */,
|
||||
62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */,
|
||||
62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */,
|
||||
628B7CE61A080E1000602C87 /* HTMLNamespaces.h */,
|
||||
6223211D1A969B9300BACED5 /* HTMLElementTypes.h */,
|
||||
6234C3361AB3BF710046F527 /* HTMLElementAdjustment.h */,
|
||||
6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */,
|
||||
@@ -611,6 +643,7 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
624717181B22333200C11912 /* HTMLNodeTraversal.h in Headers */,
|
||||
6235CE9B1AA509430026937B /* NSString+HTMLKit.h in Headers */,
|
||||
62D89DB11AE7081600B6243D /* HTMLTokenizerStates.h in Headers */,
|
||||
62079BE91AF56F1E00D3B402 /* CSSSelector.h in Headers */,
|
||||
@@ -622,10 +655,9 @@
|
||||
62D89DB51AE7081600B6243D /* HTMLElementAdjustment.h in Headers */,
|
||||
62D89DB61AE7081600B6243D /* HTMLParserInsertionModes.h in Headers */,
|
||||
62D89DB71AE7081600B6243D /* HTMLQuirksMode.h in Headers */,
|
||||
62D89DB01AE7080300B6243D /* HTMLNodes.h in Headers */,
|
||||
62D89DB01AE7080300B6243D /* HTMLDOM.h in Headers */,
|
||||
62F873EB19E088C90062683C /* HTMLParser.h in Headers */,
|
||||
624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */,
|
||||
623916C31AC707250066B4FE /* HTMLNodeTreeEnumerator.h in Headers */,
|
||||
62AE594419F992F30043F069 /* HTMLCommentToken.h in Headers */,
|
||||
624493AC19CD0CBE00BCDDF4 /* HTMLToken.h in Headers */,
|
||||
6235CEA01AA5170A0026937B /* HTMLMarker.h in Headers */,
|
||||
@@ -634,8 +666,8 @@
|
||||
623406E11ADB04F9004677A3 /* HTMLTemplate.h in Headers */,
|
||||
624B28B81B03DA820048D328 /* CSSTypeSelector.h in Headers */,
|
||||
6234BEEE1AABBF1400DEB15F /* HTMLStackOfOpenElements.h in Headers */,
|
||||
6238C9851AB8D6330006512E /* HTMLKitExceptions.h in Headers */,
|
||||
624AB3221B053A5800F3830D /* CSSSimpleSelector.h in Headers */,
|
||||
6238C9851AB8D6330006512E /* HTMLKitDOMExceptions.h in Headers */,
|
||||
6238039F1AB63A8C008A53D0 /* HTMLEOFToken.h in Headers */,
|
||||
6279F87419E1808D00F12EE5 /* HTMLElement.h in Headers */,
|
||||
62AE593F19F9907C0043F069 /* HTMLTagToken.h in Headers */,
|
||||
@@ -643,7 +675,9 @@
|
||||
624B28C41B04190D0048D328 /* NSCharacterSet+HTMLKit.h in Headers */,
|
||||
624493A619CCC54100BCDDF4 /* HTMLTokenizer.h in Headers */,
|
||||
62AE593A19F97E1C0043F069 /* HTMLDOCTYPEToken.h in Headers */,
|
||||
6247A9471B152F8C00CCF25C /* HTMLNodeFilter.h in Headers */,
|
||||
623424881AB467B200726190 /* HTMLOrderedDictionary.h in Headers */,
|
||||
6247A9431B152F4F00CCF25C /* HTMLNodeIterator.h in Headers */,
|
||||
625A150419C783EB00AD0C32 /* HTMLKit.h in Headers */,
|
||||
625A150819C78ABA00AD0C32 /* HTMLInputStreamReader.h in Headers */,
|
||||
6238579B1A9E8934003A45D9 /* HTMLComment.h in Headers */,
|
||||
@@ -654,6 +688,7 @@
|
||||
623857961A9E8606003A45D9 /* HTMLDocumentType.h in Headers */,
|
||||
623406E61ADB05AD004677A3 /* HTMLDocumentFragment.h in Headers */,
|
||||
62363C3D1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h in Headers */,
|
||||
624717BC1B22009200B38302 /* HTMLTreeWalker.h in Headers */,
|
||||
62362A3C1A9FA70400301989 /* HTMLText.h in Headers */,
|
||||
6234584E1A9D2FA4009BD491 /* HTMLNode.h in Headers */,
|
||||
);
|
||||
@@ -807,18 +842,20 @@
|
||||
files = (
|
||||
62362A3E1A9FA70400301989 /* HTMLText.m in Sources */,
|
||||
6235CE9D1AA509430026937B /* NSString+HTMLKit.m in Sources */,
|
||||
6247A9451B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */,
|
||||
6238579D1A9E8934003A45D9 /* HTMLComment.m in Sources */,
|
||||
6234BEF01AABBF1400DEB15F /* HTMLStackOfOpenElements.m in Sources */,
|
||||
624493AE19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */,
|
||||
6235CEA21AA5170A0026937B /* HTMLMarker.m in Sources */,
|
||||
6234248A1AB467B200726190 /* HTMLOrderedDictionary.m in Sources */,
|
||||
624717BE1B22009200B38302 /* HTMLTreeWalker.m in Sources */,
|
||||
62AE594119F9907C0043F069 /* HTMLTagToken.m in Sources */,
|
||||
62AE594619F992F30043F069 /* HTMLCommentToken.m in Sources */,
|
||||
62363C3F1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */,
|
||||
623916C51AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */,
|
||||
62AE593C19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */,
|
||||
623406E31ADB04F9004677A3 /* HTMLTemplate.m in Sources */,
|
||||
6238C9871AB8D6330006512E /* HTMLKitExceptions.m in Sources */,
|
||||
6238C9871AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */,
|
||||
6247171A1B22333200C11912 /* HTMLNodeTraversal.m in Sources */,
|
||||
62F873ED19E088C90062683C /* HTMLParser.m in Sources */,
|
||||
623803A11AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */,
|
||||
624B28C61B04190D0048D328 /* NSCharacterSet+HTMLKit.m in Sources */,
|
||||
@@ -826,6 +863,7 @@
|
||||
625A150A19C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */,
|
||||
623857931A9E772B003A45D9 /* HTMLDocument.m in Sources */,
|
||||
623406E81ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */,
|
||||
624717B91B21FE5400B38302 /* HTMLNodeFilter.m in Sources */,
|
||||
624493A819CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */,
|
||||
624AB3201B05373600F3830D /* CSSSimpleSequence.m in Sources */,
|
||||
623F13AC1AFC11D900C90BF4 /* CSSTokenizer.m in Sources */,
|
||||
@@ -848,6 +886,7 @@
|
||||
files = (
|
||||
6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */,
|
||||
623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */,
|
||||
6247171D1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */,
|
||||
62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */,
|
||||
624AB31B1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */,
|
||||
624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */,
|
||||
@@ -855,7 +894,7 @@
|
||||
6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */,
|
||||
624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */,
|
||||
624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */,
|
||||
623916C81AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */,
|
||||
623916C81AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m in Sources */,
|
||||
62D8345A19FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */,
|
||||
6239755F1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */,
|
||||
624FC37B1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */,
|
||||
@@ -868,18 +907,20 @@
|
||||
files = (
|
||||
62362A3D1A9FA70400301989 /* HTMLText.m in Sources */,
|
||||
6235CE9C1AA509430026937B /* NSString+HTMLKit.m in Sources */,
|
||||
6247A9441B152F4F00CCF25C /* HTMLNodeIterator.m in Sources */,
|
||||
6238579C1A9E8934003A45D9 /* HTMLComment.m in Sources */,
|
||||
6234BEEF1AABBF1400DEB15F /* HTMLStackOfOpenElements.m in Sources */,
|
||||
624493AD19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */,
|
||||
6235CEA11AA5170A0026937B /* HTMLMarker.m in Sources */,
|
||||
623424891AB467B200726190 /* HTMLOrderedDictionary.m in Sources */,
|
||||
624717BD1B22009200B38302 /* HTMLTreeWalker.m in Sources */,
|
||||
62AE594019F9907C0043F069 /* HTMLTagToken.m in Sources */,
|
||||
62AE594519F992F30043F069 /* HTMLCommentToken.m in Sources */,
|
||||
62363C3E1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */,
|
||||
623916C41AC707250066B4FE /* HTMLNodeTreeEnumerator.m in Sources */,
|
||||
62AE593B19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */,
|
||||
623406E21ADB04F9004677A3 /* HTMLTemplate.m in Sources */,
|
||||
6238C9861AB8D6330006512E /* HTMLKitExceptions.m in Sources */,
|
||||
6238C9861AB8D6330006512E /* HTMLKitDOMExceptions.m in Sources */,
|
||||
624717191B22333200C11912 /* HTMLNodeTraversal.m in Sources */,
|
||||
62F873EC19E088C90062683C /* HTMLParser.m in Sources */,
|
||||
623803A01AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */,
|
||||
624B28C51B04190D0048D328 /* NSCharacterSet+HTMLKit.m in Sources */,
|
||||
@@ -887,6 +928,7 @@
|
||||
625A150919C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */,
|
||||
623857921A9E772B003A45D9 /* HTMLDocument.m in Sources */,
|
||||
623406E71ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */,
|
||||
624717B81B21FE5400B38302 /* HTMLNodeFilter.m in Sources */,
|
||||
624493A719CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */,
|
||||
624AB31F1B05373600F3830D /* CSSSimpleSequence.m in Sources */,
|
||||
623F13AB1AFC11D900C90BF4 /* CSSTokenizer.m in Sources */,
|
||||
@@ -909,6 +951,7 @@
|
||||
files = (
|
||||
6239755A1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */,
|
||||
623CAF9D1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */,
|
||||
6247171C1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */,
|
||||
62EC7AE61AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */,
|
||||
624AB31A1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */,
|
||||
624B9FB51AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */,
|
||||
@@ -916,7 +959,7 @@
|
||||
6236738E1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */,
|
||||
624AC90119FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */,
|
||||
624B9FB21AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */,
|
||||
623916C71AC7209E0066B4FE /* HTMLKitNodeTreeEnumratorTests.m in Sources */,
|
||||
623916C71AC7209E0066B4FE /* HTMLKitNodeIteratorTests.m in Sources */,
|
||||
62D8345919FB1AC4009205A9 /* HTML5LibTokenizerTest.m in Sources */,
|
||||
6239755E1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */,
|
||||
624FC37A1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */,
|
||||
@@ -1066,7 +1109,6 @@
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
"$(inherited)",
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
);
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch";
|
||||
@@ -1089,7 +1131,6 @@
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
"$(inherited)",
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
);
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "HTMLKit/HTMLKit-Prefix.pch";
|
||||
@@ -1138,7 +1179,6 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
@@ -1162,7 +1202,6 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
#import "HTMLNode.h"
|
||||
#import "HTMLDocument.h"
|
||||
#import "HTMLDocumentType.h"
|
||||
#import "HTMLDocumentFragment.h"
|
||||
#import "HTMLElement.h"
|
||||
#import "HTMLComment.h"
|
||||
#import "HTMLText.h"
|
||||
#import "HTMLTemplate.h"
|
||||
#import "HTMLDocumentFragment.h"
|
||||
#import "HTMLNodeIterator.h"
|
||||
#import "HTMLTreeWalker.h"
|
||||
#import "HTMLNodeFilter.h"
|
||||
@@ -27,6 +27,16 @@ typedef NS_ENUM(short, HTMLDocumentReadyState)
|
||||
|
||||
@property (nonatomic, assign, readonly) HTMLDocumentReadyState readyState;
|
||||
|
||||
@property (nonatomic, strong) HTMLElement *rootElement;
|
||||
|
||||
@property (nonatomic, strong) HTMLElement *documentElement;
|
||||
|
||||
@property (nonatomic, strong) HTMLElement *head;
|
||||
|
||||
@property (nonatomic, strong) HTMLElement *body;
|
||||
|
||||
+ (instancetype)documentWithString:(NSString *)string;
|
||||
|
||||
- (HTMLNode *)adoptNode:(HTMLNode *)node;
|
||||
|
||||
- (HTMLDocument *)associatedInertTemplateDocument;
|
||||
|
||||
+103
-2
@@ -7,16 +7,25 @@
|
||||
//
|
||||
|
||||
#import "HTMLDocument.h"
|
||||
#import "HTMLKitExceptions.h"
|
||||
#import "HTMLParser.h"
|
||||
#import "HTMLNodeIterator.h"
|
||||
#import "HTMLKitDOMExceptions.h"
|
||||
|
||||
@interface HTMLNode (Private)
|
||||
@property (nonatomic, weak) HTMLDocument *ownerDocument;
|
||||
@property (nonatomic, weak) HTMLNode *parentNode;
|
||||
@end
|
||||
|
||||
@interface HTMLNodeIterator (Private)
|
||||
- (void)runRemovingStepsForNode:(HTMLNode *)oldNode
|
||||
withOldParent:(HTMLNode *)oldParent
|
||||
andOldPreviousSibling:(HTMLNode *)oldPreviousSibling;
|
||||
@end
|
||||
|
||||
@interface HTMLDocument ()
|
||||
{
|
||||
HTMLDocument *_inertTemplateDocument;
|
||||
NSMutableArray *_nodeIterators;
|
||||
}
|
||||
@property (nonatomic, assign) HTMLDocumentReadyState readyState;
|
||||
@end
|
||||
@@ -25,11 +34,18 @@
|
||||
|
||||
#pragma mark - Init
|
||||
|
||||
+ (instancetype)documentWithString:(NSString *)string
|
||||
{
|
||||
HTMLParser *parser = [[HTMLParser alloc] initWithString:string];
|
||||
return [parser parseDocument];
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super initWithName:@"#document" type:HTMLNodeDocument];
|
||||
if (self) {
|
||||
_readyState = HTMLDocumentLoading;
|
||||
_nodeIterators = [NSMutableArray new];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -57,6 +73,91 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (HTMLElement *)rootElement
|
||||
{
|
||||
for (HTMLNode *node = self.firstChild; node; node = node.nextSibling) {
|
||||
if (node.nodeType == HTMLNodeElement) {
|
||||
return node.asElement;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setRootElement:(HTMLElement *)rootElement
|
||||
{
|
||||
[self replaceChildNode:self.rootElement withNode:rootElement];
|
||||
}
|
||||
|
||||
- (HTMLElement *)documentElement
|
||||
{
|
||||
for (HTMLNode *node in [self nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]) {
|
||||
if ([node.asElement.tagName isEqualToString:@"html"]) {
|
||||
return node.asElement;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setDocumentElement:(HTMLElement *)documentElement
|
||||
{
|
||||
[self replaceChildNode:self.documentElement withNode:documentElement];
|
||||
}
|
||||
|
||||
- (HTMLElement *)head
|
||||
{
|
||||
for (HTMLNode *node in [self nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]) {
|
||||
if ([node.asElement.tagName isEqualToString:@"head"]) {
|
||||
return node.asElement;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setHead:(HTMLElement *)head
|
||||
{
|
||||
[self replaceChildNode:self.head withNode:head];
|
||||
}
|
||||
|
||||
- (HTMLElement *)body
|
||||
{
|
||||
for (HTMLNode *node in [self nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]) {
|
||||
if ([node.asElement.tagName isEqualToString:@"body"]) {
|
||||
return node.asElement;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setBody:(HTMLElement *)body
|
||||
{
|
||||
[self replaceChildNode:self.body withNode:body];
|
||||
}
|
||||
|
||||
#pragma mark - Node Iterators
|
||||
|
||||
- (void)attachNodeIterator:(HTMLNodeIterator *)iterator
|
||||
{
|
||||
[_nodeIterators addObject:iterator];
|
||||
}
|
||||
|
||||
- (void)detachNodeIterator:(HTMLNodeIterator *)iterator
|
||||
{
|
||||
[_nodeIterators removeObject:iterator];
|
||||
}
|
||||
|
||||
- (void)runRemovingStepsForNode:(HTMLNode *)oldNode
|
||||
withOldParent:(HTMLNode *)oldParent
|
||||
andOldPreviousSibling:(HTMLNode *)oldPreviousSibling
|
||||
{
|
||||
for (HTMLNodeIterator *iterator in _nodeIterators) {
|
||||
[iterator runRemovingStepsForNode:oldNode
|
||||
withOldParent:oldParent
|
||||
andOldPreviousSibling:oldPreviousSibling];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Mutation Algorithms
|
||||
|
||||
- (HTMLNode *)adoptNode:(HTMLNode *)node
|
||||
@@ -65,7 +166,7 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (node.type == HTMLNodeDocument) {
|
||||
if (node.nodeType == HTMLNodeDocument) {
|
||||
[NSException raise:HTMLKitNotSupportedError
|
||||
format:@"%@: Not Fount Error, adopting a document node. The operation is not supported.", NSStringFromSelector(_cmd)];
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
{
|
||||
NSMutableString *content = [NSMutableString string];
|
||||
for (HTMLNode *node in self.treeEnumerator) {
|
||||
if (node.type == HTMLNodeText) {
|
||||
if (node.nodeType == HTMLNodeText) {
|
||||
[content appendString:[(HTMLText *)node data]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
- (instancetype)initWithTagName:(NSString *)tagName;
|
||||
- (instancetype)initWithTagName:(NSString *)tagName attributes:(NSDictionary *)attributes;
|
||||
- (instancetype)initWithTagName:(NSString *)tagName attributes:(NSDictionary *)attributes namespace:(HTMLNamespace)htmlNamespace;
|
||||
- (instancetype)initWithTagName:(NSString *)tagName namespace:(HTMLNamespace)htmlNamespace attributes:(NSDictionary *)attributes;
|
||||
|
||||
- (BOOL)hasAttribute:(NSString *)name;
|
||||
- (NSString *)objectForKeyedSubscript:(NSString *)name;
|
||||
|
||||
+15
-6
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "HTMLElement.h"
|
||||
#import "HTMLParser.h"
|
||||
#import "HTMLDocument.h"
|
||||
#import "HTMLText.h"
|
||||
|
||||
@@ -35,10 +36,10 @@
|
||||
|
||||
- (instancetype)initWithTagName:(NSString *)tagName attributes:(NSDictionary *)attributes
|
||||
{
|
||||
return [self initWithTagName:tagName attributes:attributes namespace:HTMLNamespaceHTML];
|
||||
return [self initWithTagName:tagName namespace:HTMLNamespaceHTML attributes:attributes];
|
||||
}
|
||||
|
||||
- (instancetype)initWithTagName:(NSString *)tagName attributes:(NSDictionary *)attributes namespace:(HTMLNamespace)htmlNamespace
|
||||
- (instancetype)initWithTagName:(NSString *)tagName namespace:(HTMLNamespace)htmlNamespace attributes:(NSDictionary *)attributes
|
||||
{
|
||||
self = [super initWithName:tagName type:HTMLNodeElement];
|
||||
if (self) {
|
||||
@@ -87,8 +88,8 @@
|
||||
- (NSString *)textContent
|
||||
{
|
||||
NSMutableString *content = [NSMutableString string];
|
||||
for (HTMLNode *node in self.treeEnumerator) {
|
||||
if (node.type == HTMLNodeText) {
|
||||
for (HTMLNode *node in self.nodeIterator) {
|
||||
if (node.nodeType == HTMLNodeText) {
|
||||
[content appendString:[(HTMLText *)node data]];
|
||||
}
|
||||
}
|
||||
@@ -101,6 +102,14 @@
|
||||
[self replaceAllChildNodesWithNode:node];
|
||||
}
|
||||
|
||||
- (void)setInnerHTML:(NSString *)innerHTML
|
||||
{
|
||||
HTMLParser *parser = [[HTMLParser alloc] initWithString:innerHTML];
|
||||
NSArray *fragmentNodes = [parser parseFragmentWithContextElement:self];
|
||||
[self removeAllChildNodes];
|
||||
[self appendNodes:fragmentNodes];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
@@ -137,8 +146,8 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
if ([self.tagName isEqualToAny:@"pre", @"textarea", @"listing", nil] && self.firstChiledNode.type == HTMLNodeText) {
|
||||
HTMLText *textNode = (HTMLText *)self.firstChiledNode;
|
||||
if ([self.tagName isEqualToAny:@"pre", @"textarea", @"listing", nil] && self.firstChild.nodeType == HTMLNodeText) {
|
||||
HTMLText *textNode = (HTMLText *)self.firstChild;
|
||||
if ([textNode.data hasPrefix:@"\n"]) {
|
||||
[result appendString:@"\n"];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HTMLKitExceptions.h"
|
||||
#import "HTMLKitDOMExceptions.h"
|
||||
|
||||
NSString * const HTMLKitHierarchyRequestError = @"HierarchyRequestError";
|
||||
NSString * const HTMLKitNotFoundError = @"NotFoundError";
|
||||
+31
-11
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "HTMLNodeIterator.h"
|
||||
|
||||
typedef NS_ENUM(short, HTMLNodeType)
|
||||
{
|
||||
@@ -24,28 +25,37 @@ typedef NS_ENUM(short, HTMLNodeType)
|
||||
HTMLNodeNotation = 12 // historical
|
||||
};
|
||||
|
||||
typedef NS_ENUM(unsigned short, HTMLDocumentPosition)
|
||||
{
|
||||
HTMLDocumentPositionEquivalent = 0x0,
|
||||
HTMLDocumentPositionDisconnected = 0x01,
|
||||
HTMLDocumentPositionPreceding = 0x02,
|
||||
HTMLDocumentPositionFollowing = 0x04,
|
||||
HTMLDocumentPositionContains = 0x08,
|
||||
HTMLDocumentPositionContainedBy = 0x10,
|
||||
HTMLDocumentPositionImplementationSpecific = 0x20
|
||||
};
|
||||
|
||||
@class HTMLDocument;
|
||||
@class HTMLElement;
|
||||
|
||||
@interface HTMLNode : NSObject <NSCopying>
|
||||
|
||||
@property (nonatomic, assign, readonly) HTMLNodeType type;
|
||||
@property (nonatomic, assign, readonly) HTMLNodeType nodeType;
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *name;
|
||||
|
||||
@property (nonatomic, weak, readonly) HTMLDocument *ownerDocument;
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *baseURI;
|
||||
|
||||
@property (nonatomic, weak, readonly) HTMLNode *parentNode;
|
||||
|
||||
@property (nonatomic, weak, readonly) HTMLElement *parentElement;
|
||||
|
||||
@property (nonatomic, strong, readonly) NSOrderedSet *childNodes;
|
||||
|
||||
@property (nonatomic, strong, readonly) HTMLNode *firstChiledNode;
|
||||
@property (nonatomic, strong, readonly) HTMLNode *firstChild;
|
||||
|
||||
@property (nonatomic, strong, readonly) HTMLNode *lastChildNode;
|
||||
@property (nonatomic, strong, readonly) HTMLNode *lastChild;
|
||||
|
||||
@property (nonatomic, strong, readonly) HTMLNode *previousSibling;
|
||||
|
||||
@@ -53,10 +63,16 @@ typedef NS_ENUM(short, HTMLNodeType)
|
||||
|
||||
@property (nonatomic, copy) NSString *textContent;
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *outerHTML;
|
||||
|
||||
@property (nonatomic, copy) NSString *innerHTML;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithName:(NSString *)name type:(HTMLNodeType)type;
|
||||
|
||||
- (HTMLElement *)asElement;
|
||||
|
||||
- (BOOL)hasChildNodes;
|
||||
|
||||
- (BOOL)hasChildNodeOfType:(HTMLNodeType)type;
|
||||
@@ -91,15 +107,19 @@ typedef NS_ENUM(short, HTMLNodeType)
|
||||
|
||||
- (void)removeAllChildNodes;
|
||||
|
||||
- (HTMLDocumentPosition)compareDocumentPositionWithNode:(HTMLNode *)node;
|
||||
- (BOOL)isDescendantOfNode:(HTMLNode *)node;
|
||||
- (BOOL)containsNode:(HTMLNode *)node;
|
||||
|
||||
- (void)enumerateChildNodesUsingBlock:(void (^)(HTMLNode *node, NSUInteger idx, BOOL *stop))block;
|
||||
|
||||
- (NSEnumerator *)treeEnumerator;
|
||||
- (void)enumerateChildElementsUsingBlock:(void (^)(HTMLElement *element, NSUInteger idx, BOOL *stop))block;
|
||||
|
||||
- (NSEnumerator *)reverseTreeEnumerator;
|
||||
|
||||
- (NSString *)outerHTML;
|
||||
|
||||
- (NSString *)innerHTML;
|
||||
- (HTMLNodeIterator *)nodeIterator;
|
||||
- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(id<HTMLNodeFilter>)filter;
|
||||
- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filterBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))filter;
|
||||
|
||||
- (NSString *)treeDescription;
|
||||
|
||||
|
||||
+166
-60
@@ -12,8 +12,13 @@
|
||||
#import "HTMLElement.h"
|
||||
#import "HTMLText.h"
|
||||
#import "HTMLComment.h"
|
||||
#import "HTMLKitExceptions.h"
|
||||
#import "HTMLNodeTreeEnumerator.h"
|
||||
#import "HTMLKitDOMExceptions.h"
|
||||
|
||||
@interface HTMLDocument (Private)
|
||||
- (void)runRemovingStepsForNode:(HTMLNode *)oldNode
|
||||
withOldParent:(HTMLNode *)oldParent
|
||||
andOldPreviousSibling:(HTMLNode *)oldPreviousSibling;
|
||||
@end
|
||||
|
||||
@interface HTMLNode ()
|
||||
{
|
||||
@@ -32,7 +37,7 @@
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_name = name;
|
||||
_type = type;
|
||||
_nodeType = type;
|
||||
_childNodes = [NSMutableOrderedSet new];
|
||||
}
|
||||
return self;
|
||||
@@ -42,7 +47,7 @@
|
||||
|
||||
- (HTMLDocument *)ownerDocument
|
||||
{
|
||||
if (_type == HTMLNodeDocument) {
|
||||
if (_nodeType == HTMLNodeDocument) {
|
||||
return (HTMLDocument *)self;
|
||||
} else {
|
||||
return _ownerDocument;
|
||||
@@ -55,12 +60,6 @@
|
||||
[self.childNodes.array makeObjectsPerformSelector:@selector(setOwnerDocument:) withObject:ownerDocument];
|
||||
}
|
||||
|
||||
- (void)setBaseURI:(NSString *)baseURI
|
||||
{
|
||||
_baseURI = [baseURI copy];
|
||||
[self.childNodes.array makeObjectsPerformSelector:@selector(setBaseURI:) withObject:baseURI];
|
||||
}
|
||||
|
||||
- (void)setParentNode:(HTMLNode *)parentNode
|
||||
{
|
||||
_parentNode = parentNode;
|
||||
@@ -68,15 +67,15 @@
|
||||
|
||||
- (HTMLElement *)parentElement
|
||||
{
|
||||
return _parentNode.type == HTMLNodeElement ? (HTMLElement *)_parentNode : nil;
|
||||
return _parentNode.nodeType == HTMLNodeElement ? (HTMLElement *)_parentNode : nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)firstChiledNode
|
||||
- (HTMLNode *)firstChild
|
||||
{
|
||||
return self.childNodes.firstObject;
|
||||
}
|
||||
|
||||
- (HTMLNode *)lastChildNode
|
||||
- (HTMLNode *)lastChild
|
||||
{
|
||||
return self.childNodes.lastObject;
|
||||
}
|
||||
@@ -104,6 +103,13 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - Cast
|
||||
|
||||
- (HTMLElement *)asElement
|
||||
{
|
||||
return (HTMLElement *)self;
|
||||
}
|
||||
|
||||
#pragma mark - Child Nodes
|
||||
|
||||
- (BOOL)hasChildNodes
|
||||
@@ -114,7 +120,7 @@
|
||||
- (BOOL)hasChildNodeOfType:(HTMLNodeType)type
|
||||
{
|
||||
NSUInteger index = [self.childNodes indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if ([(HTMLNode *)obj type] == type) {
|
||||
if ([(HTMLNode *)obj nodeType] == type) {
|
||||
*stop = YES;
|
||||
return YES;
|
||||
}
|
||||
@@ -141,13 +147,13 @@
|
||||
|
||||
- (HTMLNode *)prependNode:(HTMLNode *)node
|
||||
{
|
||||
return [self insertNode:node beforeChildNode:self.firstChiledNode];
|
||||
return [self insertNode:node beforeChildNode:self.firstChild];
|
||||
}
|
||||
|
||||
- (void)prependNodes:(NSArray *)nodes
|
||||
{
|
||||
for (id node in nodes.reverseObjectEnumerator) {
|
||||
[self insertNode:node beforeChildNode:self.firstChiledNode];
|
||||
[self insertNode:node beforeChildNode:self.firstChild];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +177,7 @@
|
||||
|
||||
[self.ownerDocument adoptNode:node];
|
||||
|
||||
NSArray *nodes = node.type == HTMLNodeDocumentFragment ? [NSArray arrayWithArray:node.childNodes.array] : @[node];
|
||||
NSArray *nodes = node.nodeType == HTMLNodeDocumentFragment ? [NSArray arrayWithArray:node.childNodes.array] : @[node];
|
||||
|
||||
NSUInteger index = [self indexOfChildNode:child];
|
||||
if (index != NSNotFound) {
|
||||
@@ -181,7 +187,7 @@
|
||||
[(NSMutableOrderedSet *)self.childNodes addObjectsFromArray:nodes];
|
||||
}
|
||||
|
||||
if (node.type == HTMLNodeDocumentFragment) {
|
||||
if (node.nodeType == HTMLNodeDocumentFragment) {
|
||||
[node removeAllChildNodes];
|
||||
}
|
||||
|
||||
@@ -224,8 +230,16 @@
|
||||
NSStringFromSelector(_cmd), child];
|
||||
}
|
||||
|
||||
HTMLNode *oldNode = child;
|
||||
HTMLNode *oldParent = child.parentNode;
|
||||
HTMLNode *oldPreviousSibling = child.previousSibling;
|
||||
|
||||
[(NSMutableOrderedSet *)self.childNodes removeObject:child];
|
||||
child.parentNode = nil;
|
||||
|
||||
[self.ownerDocument runRemovingStepsForNode:oldNode
|
||||
withOldParent:oldParent
|
||||
andOldPreviousSibling:oldPreviousSibling];
|
||||
return child;
|
||||
}
|
||||
|
||||
@@ -249,6 +263,86 @@
|
||||
[(NSMutableOrderedSet *)self.childNodes removeAllObjects];
|
||||
}
|
||||
|
||||
- (HTMLDocumentPosition)compareDocumentPositionWithNode:(HTMLNode *)otherNode
|
||||
{
|
||||
if (otherNode == nil) {
|
||||
return HTMLDocumentPositionDisconnected;
|
||||
}
|
||||
|
||||
if (self == otherNode) {
|
||||
return HTMLDocumentPositionEquivalent;
|
||||
}
|
||||
|
||||
NSArray * (^ ancestorNodes) (HTMLNode *) = ^ NSArray * (HTMLNode *node) {
|
||||
NSMutableArray *ancestors = [NSMutableArray array];
|
||||
for (HTMLNode *node = self; node; node = node.parentNode) {
|
||||
[ancestors addObject:node];
|
||||
}
|
||||
return ancestors;
|
||||
};
|
||||
|
||||
NSArray *ancestors1 = ancestorNodes(self);
|
||||
NSArray *ancestors2 = ancestorNodes(otherNode);
|
||||
|
||||
if (ancestors1.lastObject != ancestors2.lastObject) {
|
||||
return HTMLDocumentPositionDisconnected |
|
||||
HTMLDocumentPositionImplementationSpecific |
|
||||
HTMLDocumentPositionFollowing;
|
||||
}
|
||||
|
||||
for (NSUInteger i = MIN(ancestors1.count - 1, ancestors2.count - 1); i; --i) {
|
||||
HTMLNode *child1 = ancestors1[i];
|
||||
HTMLNode *child2 = ancestors2[i];
|
||||
|
||||
if (child1 != child2) {
|
||||
for (HTMLNode *sibling = child1.nextSibling; sibling; sibling = sibling.nextSibling) {
|
||||
if (sibling == child2) {
|
||||
return HTMLDocumentPositionFollowing;
|
||||
}
|
||||
}
|
||||
return HTMLDocumentPositionPreceding;
|
||||
}
|
||||
}
|
||||
|
||||
if (ancestors1.count < ancestors2.count) {
|
||||
return HTMLDocumentPositionContainedBy | HTMLDocumentPositionFollowing;
|
||||
} else {
|
||||
return HTMLDocumentPositionContains | HTMLDocumentPositionPreceding;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isDescendantOfNode:(HTMLNode *)otherNode
|
||||
{
|
||||
if (otherNode == nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (self.ownerDocument != otherNode.ownerDocument) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (!otherNode.hasChildNodes) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (otherNode.nodeType == HTMLNodeDocument) {
|
||||
return self.nodeType != HTMLNodeDocument && self.ownerDocument == otherNode;
|
||||
}
|
||||
|
||||
for (HTMLNode *parentNode = self.parentNode; parentNode; parentNode = parentNode.parentNode) {
|
||||
if (parentNode == otherNode) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)containsNode:(HTMLNode *)otherNode
|
||||
{
|
||||
return self == otherNode || [otherNode isDescendantOfNode:self];
|
||||
}
|
||||
|
||||
#pragma mark - Enumeration
|
||||
|
||||
- (void)enumerateChildNodesUsingBlock:(void (^)(HTMLNode *node, NSUInteger idx, BOOL *stop))block
|
||||
@@ -262,27 +356,34 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSEnumerator *)treeEnumerator
|
||||
- (void)enumerateChildElementsUsingBlock:(void (^)(HTMLElement *element, NSUInteger idx, BOOL *stop))block
|
||||
{
|
||||
return [[HTMLNodeTreeEnumerator alloc] initWithNode:self reverse:NO];
|
||||
}
|
||||
|
||||
- (NSEnumerator *)reverseTreeEnumerator
|
||||
{
|
||||
return [[HTMLNodeTreeEnumerator alloc] initWithNode:self reverse:YES];
|
||||
}
|
||||
|
||||
- (void)doInsertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child
|
||||
{
|
||||
NSArray *nodes = node.type == HTMLNodeDocumentFragment ? node.childNodes.array : @[node];
|
||||
|
||||
NSUInteger index = [self indexOfChildNode:child];
|
||||
if (index != NSNotFound) {
|
||||
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index, nodes.count)];
|
||||
[(NSMutableOrderedSet *)self.childNodes insertObjects:nodes atIndexes:indexes];
|
||||
} else {
|
||||
[(NSMutableOrderedSet *)self.childNodes addObjectsFromArray:nodes];
|
||||
if (block == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.childNodes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if ([obj isKindOfClass:[HTMLElement class]]) {
|
||||
block([obj asElement], idx, stop);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (HTMLNodeIterator *)nodeIterator
|
||||
{
|
||||
return [self nodeIteratorWithShowOptions:HTMLNodeFilterShowAll filter:nil];
|
||||
}
|
||||
|
||||
- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(id<HTMLNodeFilter>)filter
|
||||
{
|
||||
return [[HTMLNodeIterator alloc] initWithNode:self showOptions:showOptions filter:filter];
|
||||
}
|
||||
|
||||
- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filterBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))filter
|
||||
{
|
||||
return [HTMLNodeIterator iteratorWithNode:self showOptions:showOptions filter:filter];
|
||||
}
|
||||
|
||||
#ifndef HTMLKIT_NO_DOM_CHECKS
|
||||
@@ -291,9 +392,9 @@
|
||||
|
||||
NS_INLINE void CheckParentValid(HTMLNode *parent, NSString *cmd)
|
||||
{
|
||||
if (parent.type != HTMLNodeDocument &&
|
||||
parent.type != HTMLNodeDocumentFragment &&
|
||||
parent.type != HTMLNodeElement) {
|
||||
if (parent.nodeType != HTMLNodeDocument &&
|
||||
parent.nodeType != HTMLNodeDocumentFragment &&
|
||||
parent.nodeType != HTMLNodeElement) {
|
||||
[NSException raise:HTMLKitHierarchyRequestError
|
||||
format:@"%@: Hierarchy Request Error, inserting into %@ is not allowed. The operation would yield an incorrect node tree.",
|
||||
cmd, parent.name];
|
||||
@@ -312,11 +413,11 @@ NS_INLINE void CheckChildsParent(HTMLNode *parent, HTMLNode *child, NSString *cm
|
||||
|
||||
NS_INLINE void CheckInsertedNodeValid(HTMLNode *node, NSString *cmd)
|
||||
{
|
||||
if (node.type != HTMLNodeDocumentFragment &&
|
||||
node.type != HTMLNodeDocumentType &&
|
||||
node.type != HTMLNodeElement &&
|
||||
node.type != HTMLNodeText &&
|
||||
node.type != HTMLNodeComment) {
|
||||
if (node.nodeType != HTMLNodeDocumentFragment &&
|
||||
node.nodeType != HTMLNodeDocumentType &&
|
||||
node.nodeType != HTMLNodeElement &&
|
||||
node.nodeType != HTMLNodeText &&
|
||||
node.nodeType != HTMLNodeComment) {
|
||||
[NSException raise:HTMLKitHierarchyRequestError
|
||||
format:@"%@: Hierarchy Request Error, inserting a %@ is not allowed. The operation would yield an incorrect node tree.",
|
||||
cmd, node.name];
|
||||
@@ -325,13 +426,13 @@ NS_INLINE void CheckInsertedNodeValid(HTMLNode *node, NSString *cmd)
|
||||
|
||||
NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSString *cmd)
|
||||
{
|
||||
if (node.type == HTMLNodeText && parent.type == HTMLNodeDocument) {
|
||||
if (node.nodeType == HTMLNodeText && parent.nodeType == HTMLNodeDocument) {
|
||||
[NSException raise:HTMLKitHierarchyRequestError
|
||||
format:@"%@: Hierarchy Request Error, inserting a text node %@ into docuement is not allowed. The operation would yield an incorrect node tree.",
|
||||
cmd, parent.name];
|
||||
}
|
||||
|
||||
if (node.type == HTMLNodeDocumentType && parent.type != HTMLNodeDocument) {
|
||||
if (node.nodeType == HTMLNodeDocumentType && parent.nodeType != HTMLNodeDocument) {
|
||||
[NSException raise:HTMLKitHierarchyRequestError
|
||||
format:@"%@: Hierarchy Request Error, inserting a doctype %@ into a non-document node is not allowed. The operation would yield an incorrect node tree.",
|
||||
cmd, parent.name];
|
||||
@@ -354,24 +455,24 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
NSStringFromSelector(_cmd), self, node];
|
||||
};
|
||||
|
||||
if (self.type == HTMLNodeDocument) {
|
||||
switch (node.type) {
|
||||
if (self.nodeType == HTMLNodeDocument) {
|
||||
switch (node.nodeType) {
|
||||
case HTMLNodeDocumentFragment:
|
||||
if (node.childNodesCount > 1 ||
|
||||
[node hasChildNodeOfType:HTMLNodeText]) {
|
||||
hierarchyError();
|
||||
} else if (node.childNodesCount == 1) {
|
||||
if ([self hasChildNodeOfType:HTMLNodeElement] ||
|
||||
child.type == HTMLNodeDocumentType ||
|
||||
child.nextSibling.type == HTMLNodeDocumentType) {
|
||||
child.nodeType == HTMLNodeDocumentType ||
|
||||
child.nextSibling.nodeType == HTMLNodeDocumentType) {
|
||||
hierarchyError();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HTMLNodeElement:
|
||||
if ([self hasChildNodeOfType:HTMLNodeElement] ||
|
||||
child.type == HTMLNodeDocumentType ||
|
||||
(child != nil && child.nextSibling.type == HTMLNodeDocumentType)) {
|
||||
child.nodeType == HTMLNodeDocumentType ||
|
||||
(child != nil && child.nextSibling.nodeType == HTMLNodeDocumentType)) {
|
||||
hierarchyError();
|
||||
}
|
||||
break;
|
||||
@@ -406,21 +507,21 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
|
||||
void (^ checkParentHasAnotherChildOfType)(HTMLNodeType) = ^ void (HTMLNodeType type) {
|
||||
[self enumerateChildNodesUsingBlock:^(HTMLNode *node, NSUInteger idx, BOOL *stop) {
|
||||
if (node.type == type && node != child) {
|
||||
if (node.nodeType == type && node != child) {
|
||||
*stop = YES;
|
||||
hierarchyError();
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
if (self.type == HTMLNodeDocument) {
|
||||
switch (node.type) {
|
||||
if (self.nodeType == HTMLNodeDocument) {
|
||||
switch (node.nodeType) {
|
||||
case HTMLNodeDocumentFragment:
|
||||
if (node.childNodesCount > 1 ||
|
||||
[node hasChildNodeOfType:HTMLNodeText]) {
|
||||
hierarchyError();
|
||||
} else if (node.childNodesCount == 1) {
|
||||
if (child.nextSibling.type == HTMLNodeDocumentType) {
|
||||
if (child.nextSibling.nodeType == HTMLNodeDocumentType) {
|
||||
hierarchyError();
|
||||
}
|
||||
checkParentHasAnotherChildOfType(HTMLNodeElement);
|
||||
@@ -428,7 +529,7 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
break;
|
||||
case HTMLNodeElement:
|
||||
{
|
||||
if (child.nextSibling.type == HTMLNodeDocumentType) {
|
||||
if (child.nextSibling.nodeType == HTMLNodeDocumentType) {
|
||||
hierarchyError();
|
||||
}
|
||||
checkParentHasAnotherChildOfType(HTMLNodeElement);
|
||||
@@ -436,7 +537,7 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
}
|
||||
case HTMLNodeDocumentType:
|
||||
{
|
||||
if (child.previousSibling.type == HTMLNodeElement) {
|
||||
if (child.previousSibling.nodeType == HTMLNodeElement) {
|
||||
hierarchyError();
|
||||
}
|
||||
checkParentHasAnotherChildOfType(HTMLNodeDocumentType);
|
||||
@@ -454,7 +555,7 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
HTMLNode *copy = [[self.class alloc] initWithName:self.name type:self.type];
|
||||
HTMLNode *copy = [[self.class alloc] initWithName:self.name type:self.nodeType];
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -471,6 +572,11 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
return [[self.childNodes.array valueForKey:@"outerHTML"] componentsJoinedByString:@""];
|
||||
}
|
||||
|
||||
- (void)setInnerHTML:(NSString *)outerHTML
|
||||
{
|
||||
[self doesNotRecognizeSelector:_cmd];
|
||||
}
|
||||
|
||||
#pragma mark - Description
|
||||
|
||||
- (NSString *)treeDescription
|
||||
|
||||
@@ -2,16 +2,40 @@
|
||||
// HTMLNodeFilter.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 13/05/15.
|
||||
// Created by Iska on 27/05/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(unsigned short, HTMLNodeFilterValue)
|
||||
{
|
||||
HTMLNodeFilterAccept = 1,
|
||||
HTMLNodeFilterReject = 2,
|
||||
HTMLNodeFilterSkip = 3
|
||||
};
|
||||
|
||||
typedef NS_OPTIONS(unsigned long, HTMLNodeFilterShowOptions)
|
||||
{
|
||||
HTMLNodeFilterShowAll = 0xFFFFFFFF,
|
||||
HTMLNodeFilterShowElement = 0x1,
|
||||
HTMLNodeFilterShowText = 0x4,
|
||||
HTMLNodeFilterShowComment = 0x80,
|
||||
HTMLNodeFilterShowDocument = 0x100,
|
||||
HTMLNodeFilterShowDocumentType = 0x200,
|
||||
HTMLNodeFilterShowDocumentFragment = 0x400
|
||||
};
|
||||
|
||||
@class HTMLNode;
|
||||
|
||||
@protocol HTMLNodeFilter <NSObject>
|
||||
|
||||
- (BOOL)acceptNode:(HTMLNode *)node;
|
||||
- (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node;
|
||||
|
||||
@end
|
||||
|
||||
@interface HTMLNodeFilterBlock : NSObject <HTMLNodeFilter>
|
||||
|
||||
+ (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *node))block;
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// HTMLNodeFilter.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 05/06/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HTMLNodeFilter.h"
|
||||
|
||||
@interface HTMLNodeFilterBlock ()
|
||||
{
|
||||
BOOL (^ _block)(HTMLNode *);
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation HTMLNodeFilterBlock
|
||||
|
||||
+ (instancetype)filterWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *))block
|
||||
{
|
||||
return [[self alloc] initWithBlock:block];
|
||||
}
|
||||
|
||||
- (instancetype)initWithBlock:(HTMLNodeFilterValue (^)(HTMLNode *))block
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_block = [block copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (HTMLNodeFilterValue)acceptNode:(HTMLNode *)node
|
||||
{
|
||||
if (!_block) {
|
||||
return HTMLNodeFilterSkip;
|
||||
}
|
||||
|
||||
return _block(node);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// HTMLNodeIterator.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 27/05/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "HTMLNodeFilter.h"
|
||||
|
||||
@class HTMLNode;
|
||||
|
||||
@interface HTMLNodeIterator : NSEnumerator
|
||||
|
||||
@property (nonatomic, strong, readonly) HTMLNode *root;
|
||||
@property (nonatomic, strong, readonly) HTMLNode *referenceNode;
|
||||
@property (nonatomic, assign, readonly) BOOL pointerBeforeReferenceNode;
|
||||
@property (nonatomic, assign, readonly) HTMLNodeFilterShowOptions whatToShow;
|
||||
@property (nonatomic, strong, readonly) id<HTMLNodeFilter> filter;
|
||||
|
||||
+ (instancetype)iteratorWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(HTMLNodeFilterValue (^)(HTMLNode *node))filter;
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node;
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
filter:(id<HTMLNodeFilter>)filter;
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(id<HTMLNodeFilter>)filter;
|
||||
|
||||
- (HTMLNode *)nextNode;
|
||||
- (HTMLNode *)previousNode;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// HTMLNodeIterator.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 27/05/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HTMLNodeIterator.h"
|
||||
#import "HTMLDocument.h"
|
||||
#import "HTMLNode.h"
|
||||
#import "HTMLNodeFilter.h"
|
||||
#import "HTMLNodeTraversal.h"
|
||||
|
||||
typedef NS_ENUM(short, TraverseDirection)
|
||||
{
|
||||
TraverseDirectionNext,
|
||||
TraverseDirectionPrevious
|
||||
};
|
||||
|
||||
@interface HTMLDocument (Private)
|
||||
- (void)attachNodeIterator:(HTMLNodeIterator *)iterator;
|
||||
- (void)detachNodeIterator:(HTMLNodeIterator *)iterator;
|
||||
@end
|
||||
|
||||
@interface HTMLNodeIterator ()
|
||||
{
|
||||
HTMLNode *_root;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation HTMLNodeIterator
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
+ (instancetype)iteratorWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(HTMLNodeFilterValue (^)(HTMLNode *))filter
|
||||
{
|
||||
return [[self alloc] initWithNode:node
|
||||
showOptions:showOptions
|
||||
filter:[HTMLNodeFilterBlock filterWithBlock:filter]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
{
|
||||
return [self initWithNode:node filter:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
filter:(id<HTMLNodeFilter>)filter
|
||||
{
|
||||
return [self initWithNode:node showOptions:HTMLNodeFilterShowAll filter:filter];
|
||||
}
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(id<HTMLNodeFilter>)filter
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_root = node;
|
||||
_filter = filter;
|
||||
_whatToShow = showOptions;
|
||||
_referenceNode = _root;
|
||||
_pointerBeforeReferenceNode = YES;
|
||||
[_root.ownerDocument attachNodeIterator:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_root.ownerDocument detachNodeIterator:self];
|
||||
}
|
||||
|
||||
#pragma mark - Removing Steps
|
||||
|
||||
- (void)runRemovingStepsForNode:(HTMLNode *)oldNode
|
||||
withOldParent:(HTMLNode *)oldParent
|
||||
andOldPreviousSibling:(HTMLNode *)oldPreviousSibling
|
||||
{
|
||||
if ([oldNode containsNode:_root]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (![oldNode containsNode:_referenceNode]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pointerBeforeReferenceNode) {
|
||||
HTMLNode *nextSibling = oldPreviousSibling != nil ? oldPreviousSibling.nextSibling : oldParent.firstChild;
|
||||
if (nextSibling != nil) {
|
||||
_referenceNode = nextSibling;
|
||||
return;
|
||||
}
|
||||
|
||||
HTMLNode *next = FollowingNode(oldParent, _root);
|
||||
if ([_root containsNode:next]) {
|
||||
_referenceNode = next;
|
||||
return;
|
||||
}
|
||||
|
||||
_pointerBeforeReferenceNode = NO;
|
||||
}
|
||||
|
||||
HTMLNode * (^ lastInclusiveDescendant) (HTMLNode *) = ^ HTMLNode * (HTMLNode *node) {
|
||||
while (node.lastChild) {
|
||||
node = node.lastChild;
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
_referenceNode = oldPreviousSibling != nil ? lastInclusiveDescendant(oldPreviousSibling) : oldParent;
|
||||
}
|
||||
|
||||
#pragma mark - Traversal
|
||||
|
||||
- (HTMLNode *)traverseInDirection:(TraverseDirection)direction
|
||||
{
|
||||
HTMLNode *node = self.referenceNode;
|
||||
BOOL beforeNode = self.pointerBeforeReferenceNode;
|
||||
|
||||
do {
|
||||
if (direction == TraverseDirectionNext) {
|
||||
if (!beforeNode) {
|
||||
node = FollowingNode(node, self.root);
|
||||
if (node == nil) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
beforeNode = NO;
|
||||
} else {
|
||||
if (beforeNode) {
|
||||
node = PrecedingNode(node, self.root);
|
||||
if (node == nil) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
beforeNode = YES;
|
||||
}
|
||||
} while (FilterNode(self.filter, self.whatToShow, node) != HTMLNodeFilterAccept);
|
||||
|
||||
_referenceNode = node;
|
||||
_pointerBeforeReferenceNode = beforeNode;
|
||||
return node;
|
||||
}
|
||||
|
||||
- (HTMLNode *)nextNode
|
||||
{
|
||||
return [self traverseInDirection:TraverseDirectionNext];
|
||||
}
|
||||
|
||||
- (HTMLNode *)previousNode
|
||||
{
|
||||
return [self traverseInDirection:TraverseDirectionPrevious];
|
||||
}
|
||||
|
||||
#pragma mark - NSEnumerator
|
||||
|
||||
- (id)nextObject
|
||||
{
|
||||
return self.nextNode;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// HTMLNodeTraversal.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 05/06/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "HTMLNodeFilter.h"
|
||||
|
||||
@class HTMLNode;
|
||||
|
||||
extern HTMLNode * PrecedingNode(HTMLNode *node, HTMLNode *root);
|
||||
extern HTMLNode * FollowingNode(HTMLNode *node, HTMLNode *root);
|
||||
extern HTMLNode * FollowingNodeSkippingChildren(HTMLNode *node, HTMLNode *root);
|
||||
extern HTMLNodeFilterValue FilterNode(id<HTMLNodeFilter> filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node);
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// HTMLNodeTraversal.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 05/06/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HTMLNodeTraversal.h"
|
||||
#import "HTMLNode.h"
|
||||
#import "HTMLNodeFilter.h"
|
||||
|
||||
HTMLNode * PrecedingNode(HTMLNode *node, HTMLNode *root)
|
||||
{
|
||||
HTMLNode *previous = node.previousSibling;
|
||||
if (previous != nil) {
|
||||
while (previous.lastChild != nil) {
|
||||
previous = previous.lastChild;
|
||||
}
|
||||
return previous;
|
||||
}
|
||||
|
||||
if (node == root) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return node.parentNode;
|
||||
}
|
||||
|
||||
HTMLNode * FollowingNode(HTMLNode *node, HTMLNode *root)
|
||||
{
|
||||
if (node.firstChild != nil) {
|
||||
return node.firstChild;
|
||||
}
|
||||
|
||||
do {
|
||||
if (node == root) {
|
||||
return nil;
|
||||
}
|
||||
if (node.nextSibling != nil) {
|
||||
return node.nextSibling;
|
||||
}
|
||||
node = node.parentNode;
|
||||
} while (node != nil);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
HTMLNode * FollowingNodeSkippingChildren(HTMLNode *node, HTMLNode *root)
|
||||
{
|
||||
do {
|
||||
if (node == root) {
|
||||
return nil;
|
||||
}
|
||||
if (node.nextSibling != nil) {
|
||||
return node.nextSibling;
|
||||
}
|
||||
node = node.parentNode;
|
||||
} while (node != nil);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
HTMLNodeFilterValue FilterNode(id<HTMLNodeFilter> filter, HTMLNodeFilterShowOptions whatToShow, HTMLNode *node)
|
||||
{
|
||||
unsigned long nthBit = (1 << (node.nodeType - 1)) & whatToShow;
|
||||
if (!nthBit) {
|
||||
return HTMLNodeFilterSkip;
|
||||
}
|
||||
|
||||
if (filter == nil) {
|
||||
return HTMLNodeFilterAccept;
|
||||
}
|
||||
|
||||
return [filter acceptNode:node];
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
//
|
||||
// HTMLNodeTreeEnumerator.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class HTMLNode;
|
||||
|
||||
@interface HTMLNodeTreeEnumerator : NSEnumerator
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node reverse:(BOOL)reverse;
|
||||
|
||||
@end
|
||||
@@ -1,54 +0,0 @@
|
||||
//
|
||||
// HTMLNodeTreeEnumerator.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HTMLNodeTreeEnumerator.h"
|
||||
#import "HTMLNode.h"
|
||||
|
||||
@interface HTMLNodeTreeEnumerator ()
|
||||
{
|
||||
BOOL _reverse;
|
||||
NSMutableArray *_stack;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation HTMLNodeTreeEnumerator
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node reverse:(BOOL)reverse
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_reverse = reverse;
|
||||
_stack = [[NSMutableArray alloc] initWithObjects:node, nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)nextObject
|
||||
{
|
||||
if (_stack.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
HTMLNode *node = _stack.lastObject;
|
||||
[_stack removeLastObject];
|
||||
|
||||
NSArray *childNodes = node.childNodes.array;
|
||||
if (childNodes != nil && childNodes.count > 0) {
|
||||
if (childNodes.count > 1) {
|
||||
NSRange range = NSMakeRange(_reverse ? 0 : 1, childNodes.count - 1);
|
||||
NSArray *rest = [childNodes subarrayWithRange:range];
|
||||
|
||||
[_stack addObjectsFromArray:_reverse ? rest : rest.reverseObjectEnumerator.allObjects];
|
||||
}
|
||||
[_stack addObject:_reverse ? childNodes.lastObject : childNodes.firstObject];
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -12,7 +12,7 @@
|
||||
#import "HTMLStackOfOpenElements.h"
|
||||
#import "HTMLListOfActiveFormattingElements.h"
|
||||
#import "HTMLParserInsertionModes.h"
|
||||
#import "HTMLNodes.h"
|
||||
#import "HTMLDOM.h"
|
||||
#import "HTMLElementTypes.h"
|
||||
#import "HTMLElementAdjustment.h"
|
||||
#import "HTMLMarker.h"
|
||||
@@ -421,8 +421,8 @@
|
||||
- (HTMLElement *)createElementForToken:(HTMLTagToken *)token inNamespace:(HTMLNamespace)htmlNamespace
|
||||
{
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:token.tagName
|
||||
attributes:token.attributes
|
||||
namespace:htmlNamespace];
|
||||
namespace:htmlNamespace
|
||||
attributes:token.attributes];
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -452,11 +452,11 @@
|
||||
HTMLElement *child = nil;
|
||||
HTMLNode *adjustedInsertionLocation = [self appropriatePlaceForInsertingANodeWithOverrideTarget:nil
|
||||
beforeChildNode:&child];
|
||||
if (adjustedInsertionLocation.type != HTMLNodeDocument) {
|
||||
if (child != nil && child.previousSibling.type == HTMLNodeText) {
|
||||
if (adjustedInsertionLocation.nodeType != HTMLNodeDocument) {
|
||||
if (child != nil && child.previousSibling.nodeType == HTMLNodeText) {
|
||||
[(HTMLText *)child.previousSibling appendString:data];
|
||||
} else if (adjustedInsertionLocation.lastChildNode.type == HTMLNodeText) {
|
||||
[(HTMLText *)adjustedInsertionLocation.lastChildNode appendString:data];
|
||||
} else if (adjustedInsertionLocation.lastChild.nodeType == HTMLNodeText) {
|
||||
[(HTMLText *)adjustedInsertionLocation.lastChild appendString:data];
|
||||
} else {
|
||||
HTMLText *text = [[HTMLText alloc] initWithData:data];
|
||||
[adjustedInsertionLocation insertNode:text beforeChildNode:child];
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// HTMLTreeWalker.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 05/06/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "HTMLNodeFilter.h"
|
||||
|
||||
@class HTMLNode;
|
||||
|
||||
@interface HTMLTreeWalker : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) HTMLNode *root;
|
||||
@property (nonatomic, assign, readonly) HTMLNodeFilterShowOptions whatToShow;
|
||||
@property (nonatomic, strong, readonly) id<HTMLNodeFilter> filter;
|
||||
@property (nonatomic, strong) HTMLNode *currentNode;
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node;
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
filter:(id<HTMLNodeFilter>)filter;
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(id<HTMLNodeFilter>)filter;
|
||||
|
||||
- (HTMLNode *)parentNode;
|
||||
- (HTMLNode *)firstChild;
|
||||
- (HTMLNode *)lastChild;
|
||||
- (HTMLNode *)previousSibling;
|
||||
- (HTMLNode *)nextSibling;
|
||||
- (HTMLNode *)previousNode;
|
||||
- (HTMLNode *)nextNode;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,236 @@
|
||||
//
|
||||
// HTMLTreeWalker.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 05/06/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HTMLTreeWalker.h"
|
||||
#import "HTMLNode.h"
|
||||
#import "HTMLNodeFilter.h"
|
||||
#import "HTMLNodeTraversal.h"
|
||||
|
||||
typedef NS_ENUM(short, HTMLTreeWalkerChildrenType)
|
||||
{
|
||||
HTMLTreeWalkerChildrenTypeFirst,
|
||||
HTMLTreeWalkerChildrenTypeLast
|
||||
};
|
||||
|
||||
typedef NS_ENUM(short, HTMLTreeWalkerSiblingsType)
|
||||
{
|
||||
HTMLTreeWalkerSiblingsTypeNext,
|
||||
HTMLTreeWalkerSiblingsTypePrevious
|
||||
};
|
||||
|
||||
@implementation HTMLTreeWalker
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
{
|
||||
return [self initWithNode:node filter:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
filter:(id<HTMLNodeFilter>)filter
|
||||
{
|
||||
return [self initWithNode:node showOptions:HTMLNodeFilterShowAll filter:filter];
|
||||
}
|
||||
|
||||
- (instancetype)initWithNode:(HTMLNode *)node
|
||||
showOptions:(HTMLNodeFilterShowOptions)showOptions
|
||||
filter:(id<HTMLNodeFilter>)filter
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_root = node;
|
||||
_filter = filter;
|
||||
_whatToShow = showOptions;
|
||||
_currentNode = _root;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Traversal
|
||||
|
||||
- (HTMLNode *)parentNode
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
while (node != nil && node != _root) {
|
||||
node = node.parentNode;
|
||||
if (node != nil && FilterNode(self.filter, self.whatToShow, node) == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)traverseChildrenOfType:(HTMLTreeWalkerChildrenType)type
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
node = (type == HTMLTreeWalkerChildrenTypeFirst) ? node.firstChild : node.lastChild;
|
||||
|
||||
while (node != nil) {
|
||||
HTMLNodeFilterValue result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
if (result == HTMLNodeFilterSkip) {
|
||||
HTMLNode *child = (type == HTMLTreeWalkerChildrenTypeFirst) ? node.firstChild : node.lastChild;
|
||||
if (child != nil) {
|
||||
node = child;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
while (node != nil) {
|
||||
HTMLNode *sibling = (type == HTMLTreeWalkerChildrenTypeFirst) ? node.nextSibling : node.previousSibling;
|
||||
if (sibling != nil) {
|
||||
node = sibling;
|
||||
break;
|
||||
}
|
||||
|
||||
HTMLNode *parent = node.parentNode;
|
||||
if (parent == nil || parent == _root || parent == _currentNode) {
|
||||
return nil;
|
||||
}
|
||||
node = parent;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)firstChild
|
||||
{
|
||||
return [self traverseChildrenOfType:HTMLTreeWalkerChildrenTypeFirst];
|
||||
}
|
||||
|
||||
- (HTMLNode *)lastChild
|
||||
{
|
||||
return [self traverseChildrenOfType:HTMLTreeWalkerChildrenTypeLast];
|
||||
}
|
||||
|
||||
- (HTMLNode *)traverseSiblingsOfType:(HTMLTreeWalkerSiblingsType)type
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
if (node == _root) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
while (YES) {
|
||||
HTMLNode *sibling = (type == HTMLTreeWalkerSiblingsTypeNext) ? node.nextSibling : node.previousSibling;
|
||||
while (sibling != nil) {
|
||||
node = sibling;
|
||||
HTMLNodeFilterValue result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
sibling = (type == HTMLTreeWalkerSiblingsTypeNext) ? node.firstChild : node.lastChild;
|
||||
if (result == HTMLNodeFilterReject || sibling == nil) {
|
||||
sibling = (type == HTMLTreeWalkerSiblingsTypeNext) ? node.nextSibling : node.previousSibling;
|
||||
}
|
||||
}
|
||||
|
||||
node = node.parentNode;
|
||||
if (node == nil || node == _root) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (FilterNode(self.filter, self.whatToShow, node) == HTMLNodeFilterAccept) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)previousSibling
|
||||
{
|
||||
return [self traverseSiblingsOfType:HTMLTreeWalkerSiblingsTypePrevious];
|
||||
}
|
||||
|
||||
- (HTMLNode *)nextSibling
|
||||
{
|
||||
return [self traverseSiblingsOfType:HTMLTreeWalkerSiblingsTypeNext];
|
||||
}
|
||||
|
||||
- (HTMLNode *)previousNode
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
while (node != _root) {
|
||||
HTMLNode *sibling = node.previousSibling;
|
||||
|
||||
while (sibling != nil) {
|
||||
node = sibling;
|
||||
|
||||
HTMLNodeFilterValue result = FilterNode(self.filter, self.whatToShow, node);
|
||||
while (result != HTMLNodeFilterReject && node.hasChildNodes) {
|
||||
node = node.lastChild;
|
||||
result = FilterNode(self.filter, self.whatToShow, node);
|
||||
}
|
||||
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
sibling = node.previousSibling;
|
||||
}
|
||||
|
||||
if (node == _root || node.parentNode == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
node = node.parentNode;
|
||||
if (FilterNode(self.filter, self.whatToShow, node) == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (HTMLNode *)nextNode
|
||||
{
|
||||
HTMLNode *node = _currentNode;
|
||||
|
||||
HTMLNodeFilterValue result = YES;
|
||||
|
||||
while (YES) {
|
||||
while (result != HTMLNodeFilterReject && node.hasChildNodes) {
|
||||
node = node.firstChild;
|
||||
result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
HTMLNode *nextSibling;
|
||||
while ((nextSibling = FollowingNodeSkippingChildren(node, _root)) != nil) {
|
||||
node = nextSibling;
|
||||
result = FilterNode(self.filter, self.whatToShow, node);
|
||||
if (result == HTMLNodeFilterAccept) {
|
||||
_currentNode = node;
|
||||
return node;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -13,7 +13,6 @@
|
||||
#import "HTMLElement.h"
|
||||
#import "HTMLText.h"
|
||||
#import "HTMLComment.h"
|
||||
#import "HTMLNodeTreeEnumerator.h"
|
||||
|
||||
static NSString * const HTML5LibTests = @"html5lib-tests";
|
||||
static NSString * const TreeConstruction = @"tree-construction";
|
||||
@@ -111,7 +110,7 @@ static NSString * const TreeConstruction = @"tree-construction";
|
||||
fragment = [fragment substringFromIndex:@"svg ".length];
|
||||
namespace = HTMLNamespaceSVG;
|
||||
}
|
||||
test.documentFragment = [[HTMLElement alloc] initWithTagName:fragment attributes:nil namespace:namespace];
|
||||
test.documentFragment = [[HTMLElement alloc] initWithTagName:fragment namespace:namespace attributes:nil];
|
||||
} else if ([match hasPrefix:@"#document\n"]) {
|
||||
NSArray *parts = [[match substringFromIndex:@"#document\n".length] componentsSeparatedByString:@"| "];
|
||||
NSArray *nodes = [HTML5LibTreeConstructionTest parseDocument:parts];
|
||||
@@ -245,7 +244,7 @@ NS_INLINE HTMLElement * parseTag(NSString *str)
|
||||
NSString *tagName = parts.count == 2 ? parts[1] : parts[0];
|
||||
HTMLNamespace namespace = parts.count == 1 ? HTMLNamespaceHTML : ([parts[0] isEqualToString:@"math"] ? HTMLNamespaceMathML : HTMLNamespaceSVG);
|
||||
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:tagName attributes:nil namespace:namespace];
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:tagName namespace:namespace attributes:nil];
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "HTMLNodes.h"
|
||||
#import "HTMLDOM.h"
|
||||
#import "NSString+HTMLKit.h"
|
||||
|
||||
extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));
|
||||
|
||||
@@ -0,0 +1,568 @@
|
||||
//
|
||||
// HTMLKitNodeTreeEnumratorTests.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "HTMLDOM.h"
|
||||
|
||||
@interface HTMLKitNodeIteratorTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation HTMLKitNodeIteratorTests
|
||||
|
||||
#pragma mark - Test DOM
|
||||
|
||||
- (HTMLElement *)div
|
||||
{
|
||||
return [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
}
|
||||
|
||||
- (HTMLElement *)simpleTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"a"]];
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"b"]];
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"c"]];
|
||||
return div;
|
||||
}
|
||||
|
||||
- (HTMLElement *)nestedSimpleTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:self.simpleTree];
|
||||
[div appendNode:self.simpleTree];
|
||||
return div;
|
||||
}
|
||||
|
||||
- (HTMLElement *)complexTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| div
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
| e
|
||||
| f
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *root = self.div;
|
||||
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:self.simpleTree];
|
||||
[root appendNode:div];
|
||||
|
||||
HTMLElement *e = [[HTMLElement alloc] initWithTagName:@"e"];
|
||||
[e appendNode:[[HTMLElement alloc] initWithTagName:@"f"]];
|
||||
[root appendNode:e];
|
||||
[root appendNode:self.simpleTree];
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
- (HTMLDocument *)mixedTree
|
||||
{
|
||||
|
||||
/*
|
||||
| doctype
|
||||
| #comment <!-- This is a Comment -->
|
||||
| #comment <!-- This is a second Comment -->
|
||||
| html
|
||||
| #text "This is a Text"
|
||||
| div
|
||||
*/
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
document.documentType = [HTMLDocumentType new];;
|
||||
|
||||
HTMLComment *comment = [[HTMLComment alloc] initWithData:@"This is a Comment"];
|
||||
[document appendNode:comment];
|
||||
|
||||
HTMLComment *secondCommnet = [[HTMLComment alloc] initWithData:@"This is a second Comment"];
|
||||
[document appendNode:secondCommnet];
|
||||
|
||||
HTMLElement *root = [[HTMLElement alloc] initWithTagName:@"html"];
|
||||
[document appendNode:root];
|
||||
|
||||
[root appendNode:[[HTMLText alloc] initWithData:@"This is a Text"]];
|
||||
|
||||
[root appendNode:[[HTMLElement alloc] initWithTagName:@"div"]];
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
- (HTMLDocument *)document
|
||||
{
|
||||
NSString *htmlString =
|
||||
@"<!DOCTYPE html>"
|
||||
@"<html>"
|
||||
@"<head>"
|
||||
@"<title>Title</title>"
|
||||
@"</head>"
|
||||
@"<body>"
|
||||
@"<span>Hello<strong>World!</strong><strong>HTML <!-- This is a Comment! --> Kit</strong></span>"
|
||||
@"<p>This is an <em>Important</em> paragraph</p>"
|
||||
@"</body>"
|
||||
@"</html>";
|
||||
|
||||
HTMLDocument *document = [HTMLDocument documentWithString:htmlString];
|
||||
return document;
|
||||
}
|
||||
|
||||
#pragma mark - Test Iterator
|
||||
|
||||
- (void)testNodeIteratorInit
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
HTMLNodeIterator *iterator = tree.nodeIterator;
|
||||
|
||||
XCTAssertEqualObjects(iterator.root, tree);
|
||||
XCTAssertEqualObjects(iterator.referenceNode, tree);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
XCTAssertEqualObjects(iterator.filter, nil);
|
||||
XCTAssertEqual(iterator.whatToShow, HTMLNodeFilterShowAll);
|
||||
}
|
||||
|
||||
- (void)testNewIteratorNextNodeShouldBeRoot
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
HTMLNodeIterator *iterator = tree.nodeIterator;
|
||||
|
||||
XCTAssertEqualObjects(iterator.nextNode, tree);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
|
||||
}
|
||||
|
||||
- (void)testNewIteratorPreviousNodeShouldBeNil
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
HTMLNodeIterator *iterator = tree.nodeIterator;
|
||||
|
||||
XCTAssertEqualObjects(iterator.previousNode, nil);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
}
|
||||
|
||||
- (void)testNewIteratorPreviousNodeShouldBeNextNode
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
HTMLNodeIterator *iterator = tree.nodeIterator;
|
||||
|
||||
HTMLNode *node = iterator.nextNode;
|
||||
|
||||
XCTAssertEqualObjects(iterator.previousNode, node);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
}
|
||||
|
||||
- (void)testNextPreviousIteration
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
HTMLNodeIterator *iterator = tree.nodeIterator;
|
||||
|
||||
XCTAssertEqualObjects(iterator.previousNode, nil);
|
||||
XCTAssertEqualObjects(iterator.nextNode.name, @"div");
|
||||
XCTAssertEqualObjects(iterator.nextNode.name, @"a");
|
||||
XCTAssertEqualObjects(iterator.previousNode.name, @"a");
|
||||
XCTAssertEqualObjects(iterator.previousNode.name, @"div");
|
||||
XCTAssertEqualObjects(iterator.nextNode.name, @"div");
|
||||
XCTAssertEqualObjects(iterator.nextNode.name, @"a");
|
||||
XCTAssertEqualObjects(iterator.nextNode.name, @"b");
|
||||
XCTAssertEqualObjects(iterator.nextNode.name, @"c");
|
||||
XCTAssertEqualObjects(iterator.previousNode.name, @"c");
|
||||
XCTAssertEqualObjects(iterator.previousNode.name, @"b");
|
||||
XCTAssertEqualObjects(iterator.previousNode.name, @"a");
|
||||
XCTAssertEqualObjects(iterator.previousNode.name, @"div");
|
||||
}
|
||||
|
||||
- (void)testSingleNodeIteration
|
||||
{
|
||||
HTMLElement *div = self.div;
|
||||
NSArray *result = div.nodeIterator.allObjects;
|
||||
NSArray *expected = @[@"div"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testSimpleTreeIteration
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
NSArray *result = tree.nodeIterator.allObjects;
|
||||
NSArray *expected = @[@"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testNestedSimpleTreeIteration
|
||||
{
|
||||
HTMLElement *tree = self.nestedSimpleTree;
|
||||
NSArray *result = tree.nodeIterator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div", @"a", @"b", @"c", @"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testComplexTreeIteration
|
||||
{
|
||||
HTMLElement *tree = self.complexTree;
|
||||
NSArray *result = tree.nodeIterator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div",@"div", @"a", @"b", @"c", @"e", @"f", @"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
#pragma mark - Test Iterator ShowOptions (WhatToShow)
|
||||
|
||||
- (void)testShowDocument
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowDocument filter:nil];
|
||||
NSArray *result = iterator.allObjects;
|
||||
NSArray *expected = @[@"#document"];
|
||||
XCTAssertEqual(result.count, 1);
|
||||
XCTAssertEqual([result.firstObject class], [HTMLDocument class]);
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testShowDocumentType
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowDocumentType filter:nil];
|
||||
NSArray *result = iterator.allObjects;
|
||||
NSArray *expected = @[@"html"];
|
||||
XCTAssertEqual(result.count, 1);
|
||||
XCTAssertEqual([result.firstObject class], [HTMLDocumentType class]);
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testShowComment
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowComment filter:nil];
|
||||
NSArray *result = iterator.allObjects;
|
||||
NSArray *expected = @[@"#comment", @"#comment"];
|
||||
XCTAssertEqual(result.count, 2);
|
||||
XCTAssertEqual([result[0] class], [HTMLComment class]);
|
||||
XCTAssertEqual([result[1] class], [HTMLComment class]);
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testShowText
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowText filter:nil];
|
||||
NSArray *result = iterator.allObjects;
|
||||
NSArray *expected = @[@"#text"];
|
||||
XCTAssertEqual(result.count, 1);
|
||||
XCTAssertEqual([result.firstObject class], [HTMLText class]);
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testShowElement
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil];
|
||||
NSArray *result = iterator.allObjects;
|
||||
NSArray *expected = @[@"html", @"div"];
|
||||
XCTAssertEqual(result.count, 2);
|
||||
XCTAssertEqual([result.firstObject class], [HTMLElement class]);
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testShowBitmask
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowElement | HTMLNodeFilterShowText
|
||||
filter:nil];
|
||||
NSArray *result = iterator.allObjects;
|
||||
NSArray *expected = @[@"html", @"#text", @"div"];
|
||||
XCTAssertEqual(result.count, 3);
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
#pragma mark - Test Iterator Filter
|
||||
|
||||
- (void)testNodeFilter
|
||||
{
|
||||
HTMLDocument *document = self.mixedTree;
|
||||
|
||||
HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowAll
|
||||
filterBlock:^HTMLNodeFilterValue(HTMLNode *node) {
|
||||
if (node.nodeType == HTMLNodeComment) {
|
||||
if ([[(HTMLComment *)node data] rangeOfString:@"second"].location != NSNotFound) {
|
||||
return HTMLNodeFilterAccept;
|
||||
}
|
||||
}
|
||||
return HTMLNodeFilterSkip;
|
||||
}];
|
||||
|
||||
NSArray *result = iterator.allObjects;
|
||||
NSArray *expected = @[@"#comment"];
|
||||
XCTAssertEqual(result.count, 1);
|
||||
XCTAssertEqualObjects([result[0] data], @"This is a second Comment");
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
#pragma mark - Test Removing Steps
|
||||
|
||||
/*
|
||||
Test cases for the Removing Steps
|
||||
https://dom.spec.whatwg.org/#interface-nodeiterator
|
||||
|
||||
Following DOM is used:
|
||||
|
||||
| <html>
|
||||
| <head>
|
||||
| <title>
|
||||
| "Title"
|
||||
| <body>
|
||||
| <span>
|
||||
| "Hello"
|
||||
| <strong>
|
||||
| "World!"
|
||||
| <strong>
|
||||
| "HTML "
|
||||
| <!-- This is a Comment! -->
|
||||
| " Kit"
|
||||
| <p>
|
||||
| "This is an "
|
||||
| <em>
|
||||
| "Important"
|
||||
| " paragraph"
|
||||
*/
|
||||
|
||||
static void (^ RemoveThenInsertNode)(HTMLNode *) = ^ (HTMLNode *node) {
|
||||
HTMLNode *parent = node.parentNode;
|
||||
HTMLNode *nextSibling = node.nextSibling;
|
||||
[parent removeChildNode:node];
|
||||
[parent insertNode:node beforeChildNode:nextSibling];
|
||||
};
|
||||
|
||||
static void (^ IterateUpToNode)(HTMLNodeIterator *, HTMLNode *) = ^ (HTMLNodeIterator *iterator, HTMLNode *target) {
|
||||
for(HTMLNode *node = iterator.referenceNode; node && (node != target); node = iterator.nextNode);
|
||||
};
|
||||
|
||||
static HTMLNode * (^ LastDescendant)(HTMLNode *) = ^ HTMLNode * (HTMLNode *node) {
|
||||
while (node.lastChild) {
|
||||
node = node.lastChild;
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
- (void)testThatRemovingRootNodeShouldNotAffectIterator
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *node = document.body.firstChild; // <span>
|
||||
|
||||
HTMLNodeIterator *iterator = node.nodeIterator;
|
||||
|
||||
[document.body removeChildNode:node];
|
||||
|
||||
XCTAssertEqualObjects(iterator.root, node);
|
||||
XCTAssertEqualObjects(iterator.referenceNode, node);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
XCTAssertEqualObjects(iterator.referenceNode.parentNode, nil);
|
||||
}
|
||||
|
||||
- (void)testThatRemovingANonInclusiveAnscestorOfReferenceShouldNotAffectIterator
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *body = document.body;
|
||||
|
||||
HTMLNodeIterator *iterator = body.nodeIterator;
|
||||
|
||||
[iterator nextNode]; // Reference node: <body>
|
||||
[iterator nextNode]; // Reference node: <span>
|
||||
|
||||
RemoveThenInsertNode(iterator.root.childNodes[1]); // Remove <p>
|
||||
|
||||
XCTAssertEqualObjects(iterator.root, body);
|
||||
XCTAssertEqualObjects(iterator.referenceNode, body.firstChild);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
|
||||
}
|
||||
|
||||
- (void)testThatRemovingReferenceNodeShouldUpdateIterator_NilOldPreviousSibling
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
|
||||
HTMLNodeIterator *iterator = document.body.nodeIterator;
|
||||
|
||||
[iterator nextNode]; // Reference node: <body>
|
||||
|
||||
HTMLNode *node = iterator.nextNode; // Reference node: <span>
|
||||
RemoveThenInsertNode(node); // Remove <span> with old previos sibling being nil
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, iterator.root);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
|
||||
|
||||
HTMLNode *next = iterator.nextNode; // "Hello"
|
||||
XCTAssertEqualObjects(next, iterator.root.firstChild);
|
||||
}
|
||||
|
||||
- (void)testThatRemovingReferenceNodeShouldUpdateIterator_NonNilOldPreviousSibling_NotBeforeReference
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *body = document.body;
|
||||
|
||||
HTMLNodeIterator *iterator = body.nodeIterator;
|
||||
|
||||
HTMLNode *node = iterator.root.childNodes[1]; // <p>
|
||||
IterateUpToNode(iterator, node); // Reference node: <p>, pointer-before-reference: NO
|
||||
RemoveThenInsertNode(node); // Remove <p> with old previos sibling being <span>
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, LastDescendant(body.firstChild));
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
|
||||
}
|
||||
|
||||
- (void)testThatRemovingReferenceNodeShouldUpdateIterator_NonNilOldPreviousSibling_BeforeReference
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *body = document.body;
|
||||
|
||||
HTMLNodeIterator *iterator = body.nodeIterator;
|
||||
|
||||
HTMLNode *node = iterator.root.childNodes[1]; // <p>
|
||||
IterateUpToNode(iterator, node); // Reference node: <p>, pointer-before-reference: NO
|
||||
[iterator previousNode]; // pointer-before-reference: YES
|
||||
RemoveThenInsertNode(node); // Remove <p> with old previos sibling being <span>
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, body.firstChild);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
}
|
||||
|
||||
- (void)testThatRemovingThenReinsertingReferenceNodeAfterNextShouldReturnItAgain
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNodeIterator *iterator = document.body.nodeIterator;
|
||||
|
||||
[iterator nextNode]; // Reference node: <body>
|
||||
|
||||
HTMLNode *node = iterator.nextNode; // <span>
|
||||
RemoveThenInsertNode(node);
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, iterator.root);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
|
||||
|
||||
HTMLNode *next = iterator.nextNode;
|
||||
XCTAssertEqualObjects(next, node);
|
||||
}
|
||||
|
||||
- (void)testThatRemovingThenReinsertingReferenceNodeAfterPreviousShouldReturnItAgain
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNodeIterator *iterator = document.body.nodeIterator;
|
||||
|
||||
[iterator nextNode]; // Reference node: <body>
|
||||
[iterator nextNode]; // Reference node: <span>
|
||||
|
||||
HTMLNode *node = iterator.previousNode; // Reference node: <span>, pointer-before-reference: YES
|
||||
HTMLNode *next = node.nextSibling; // <p>
|
||||
RemoveThenInsertNode(node);
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, next);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
|
||||
HTMLNode *previous = iterator.previousNode;
|
||||
XCTAssertEqualObjects(previous, LastDescendant(node));
|
||||
}
|
||||
|
||||
- (void)testThatRemovingParentOfReferenceNodeShouldUpdateIterator_NotBeforeReference
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *body = document.body;
|
||||
|
||||
HTMLNodeIterator *iterator = body.nodeIterator;
|
||||
HTMLNode *parent = body.childNodes[1];
|
||||
|
||||
IterateUpToNode(iterator, parent); // Reference node: <p>, pointer-before-reference: NO
|
||||
[iterator nextNode]; // Reference node: "This is an "
|
||||
RemoveThenInsertNode(parent);
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, LastDescendant(body.firstChild));
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
|
||||
}
|
||||
|
||||
- (void)testThatRemovingParentOfReferenceNodeShouldUpdateIterator_BeforeReference
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *body = document.body;
|
||||
|
||||
HTMLNodeIterator *iterator = body.nodeIterator;
|
||||
HTMLNode *parent = body.childNodes[1];
|
||||
|
||||
IterateUpToNode(iterator, parent); // Reference node: <p>, pointer-before-reference: NO
|
||||
[iterator nextNode]; // Reference node: "This is an "
|
||||
[iterator previousNode]; // pointer-before-reference: YES
|
||||
RemoveThenInsertNode(parent);
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, body.firstChild);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
}
|
||||
|
||||
- (void)testRemoveReferenceNode_NilPreviousSibling_NonNilParentFirstChild
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *body = document.body;
|
||||
|
||||
HTMLNodeIterator *iterator = body.nodeIterator;
|
||||
|
||||
[iterator nextNode]; // Reference node: <body>
|
||||
[iterator nextNode]; // Reference node: <span>
|
||||
|
||||
HTMLNode *node = iterator.previousNode; // Reference node: <span>, pointer-before-reference: YES
|
||||
XCTAssertNil(node.previousSibling);
|
||||
XCTAssertNotNil(node.nextSibling);
|
||||
|
||||
HTMLNode *nextSibling = node.nextSibling; // <p>
|
||||
RemoveThenInsertNode(node);
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, nextSibling);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
|
||||
|
||||
HTMLNode *next = iterator.nextNode; // <p>
|
||||
XCTAssertNotEqualObjects(next, node);
|
||||
XCTAssertEqualObjects(next, nextSibling);
|
||||
}
|
||||
|
||||
- (void)testRemoveReferenceNode_NodeAfterOldParentIsOutsideRoot_BeforeReference
|
||||
{
|
||||
HTMLDocument *document = self.document;
|
||||
HTMLNode *body = document.body;
|
||||
|
||||
body.innerHTML = @"<div><p><a></a></p></div><div></div>";
|
||||
|
||||
HTMLNodeIterator *iterator = body.firstChild.nodeIterator;
|
||||
|
||||
IterateUpToNode(iterator, LastDescendant(body.firstChild)); // Referecne node: <a>
|
||||
HTMLNode *node = [iterator previousNode]; // pointer-before-reference: YES
|
||||
RemoveThenInsertNode(node);
|
||||
|
||||
XCTAssertEqualObjects(iterator.referenceNode, iterator.root.firstChild);
|
||||
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,148 +0,0 @@
|
||||
//
|
||||
// HTMLKitNodeTreeEnumratorTests.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 28/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "HTMLNodes.h"
|
||||
|
||||
@interface HTMLKitNodeTreeEnumratorTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation HTMLKitNodeTreeEnumratorTests
|
||||
|
||||
#pragma mark - Elements
|
||||
|
||||
- (HTMLElement *)div
|
||||
{
|
||||
return [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
}
|
||||
|
||||
- (HTMLElement *)simpleTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"a"]];
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"b"]];
|
||||
[div appendNode:[[HTMLElement alloc] initWithTagName:@"c"]];
|
||||
return div;
|
||||
}
|
||||
|
||||
- (HTMLElement *)nestedSimpleTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:self.simpleTree];
|
||||
[div appendNode:self.simpleTree];
|
||||
return div;
|
||||
}
|
||||
|
||||
- (HTMLElement *)complexTree
|
||||
{
|
||||
/*
|
||||
| div
|
||||
| div
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
| e
|
||||
| f
|
||||
| div
|
||||
| a
|
||||
| b
|
||||
| c
|
||||
*/
|
||||
HTMLElement *root = self.div;
|
||||
|
||||
HTMLElement *div = self.div;
|
||||
[div appendNode:self.simpleTree];
|
||||
[root appendNode:div];
|
||||
|
||||
HTMLElement *e = [[HTMLElement alloc] initWithTagName:@"e"];
|
||||
[e appendNode:[[HTMLElement alloc] initWithTagName:@"f"]];
|
||||
[root appendNode:e];
|
||||
[root appendNode:self.simpleTree];
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
#pragma mark - Tests
|
||||
|
||||
- (void)testSingle
|
||||
{
|
||||
HTMLElement *div = self.div;
|
||||
NSArray *result = div.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testSimpleTree
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
NSArray *result = tree.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testSimpleTreeReversed
|
||||
{
|
||||
HTMLElement *tree = self.simpleTree;
|
||||
NSArray *result = tree.reverseTreeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"c", @"b", @"a"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testNestedSimpleTree
|
||||
{
|
||||
HTMLElement *tree = self.nestedSimpleTree;
|
||||
NSArray *result = tree.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div", @"a", @"b", @"c", @"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testNestedSimpleTreeReversed
|
||||
{
|
||||
HTMLElement *tree = self.nestedSimpleTree;
|
||||
NSArray *result = tree.reverseTreeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div", @"c", @"b", @"a", @"div", @"c", @"b", @"a"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testComplexSimpleTree
|
||||
{
|
||||
HTMLElement *tree = self.complexTree;
|
||||
NSArray *result = tree.treeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div",@"div", @"a", @"b", @"c", @"e", @"f", @"div", @"a", @"b", @"c"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
- (void)testComplexSimpleTreeReversed
|
||||
{
|
||||
HTMLElement *tree = self.complexTree;
|
||||
NSArray *result = tree.reverseTreeEnumerator.allObjects;
|
||||
NSArray *expected = @[@"div", @"div", @"c", @"b", @"a", @"e", @"f", @"div", @"div", @"c", @"b", @"a"];
|
||||
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "HTMLNodes.h"
|
||||
#import "HTMLDOM.h"
|
||||
|
||||
@interface HTMLKitNodesTests : XCTestCase
|
||||
|
||||
@@ -30,18 +30,17 @@
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
XCTAssertNotNil(node);
|
||||
XCTAssertEqualObjects(node.name, @"name");
|
||||
XCTAssertEqual(node.type, HTMLNodeElement);
|
||||
XCTAssertEqual(node.nodeType, HTMLNodeElement);
|
||||
XCTAssertNotNil(node.childNodes);
|
||||
XCTAssertEqual(node.childNodes.count, 0);
|
||||
|
||||
XCTAssertNil(node.ownerDocument);
|
||||
XCTAssertNil(node.baseURI);
|
||||
XCTAssertNil(node.parentNode);
|
||||
XCTAssertNil(node.parentElement);
|
||||
XCTAssertNil(node.firstChiledNode);
|
||||
XCTAssertNil(node.lastChildNode);
|
||||
XCTAssertNil(node.firstChild);
|
||||
XCTAssertNil(node.lastChild);
|
||||
XCTAssertNil(node.previousSibling);
|
||||
XCTAssertNil(node.lastChildNode);
|
||||
XCTAssertNil(node.lastChild);
|
||||
}
|
||||
|
||||
- (void)testAppendNode
|
||||
@@ -51,7 +50,7 @@
|
||||
[element appendNode:comment];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 1);
|
||||
XCTAssertEqual(element.firstChiledNode, comment);
|
||||
XCTAssertEqual(element.firstChild, comment);
|
||||
|
||||
HTMLElement *firstElement = [HTMLElement new];
|
||||
HTMLElement *secondElement = [HTMLElement new];
|
||||
@@ -60,8 +59,8 @@
|
||||
[element appendNodes:nodes];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 3);
|
||||
XCTAssertEqual(element.firstChiledNode, comment);
|
||||
XCTAssertEqual(element.lastChildNode, secondElement);
|
||||
XCTAssertEqual(element.firstChild, comment);
|
||||
XCTAssertEqual(element.lastChild, secondElement);
|
||||
}
|
||||
|
||||
- (void)testPrependNode
|
||||
@@ -74,7 +73,7 @@
|
||||
[element prependNode:comment];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 2);
|
||||
XCTAssertEqual(element.firstChiledNode, comment);
|
||||
XCTAssertEqual(element.firstChild, comment);
|
||||
|
||||
HTMLElement *firstElement = [HTMLElement new];
|
||||
HTMLElement *secondElement = [HTMLElement new];
|
||||
@@ -83,8 +82,8 @@
|
||||
[element prependNodes:nodes];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 4);
|
||||
XCTAssertEqual(element.firstChiledNode, firstElement);
|
||||
XCTAssertEqual(element.lastChildNode, text);
|
||||
XCTAssertEqual(element.firstChild, firstElement);
|
||||
XCTAssertEqual(element.lastChild, text);
|
||||
}
|
||||
|
||||
- (void)testAppendDocumentFragment
|
||||
@@ -105,10 +104,10 @@
|
||||
|
||||
XCTAssertEqualObjects(firstChild.parentNode, element);
|
||||
XCTAssertEqualObjects(secondChild.parentNode, element);
|
||||
XCTAssertEqualObjects(element.firstChiledNode, comment);
|
||||
XCTAssertEqualObjects(element.firstChiledNode.nextSibling, firstChild);
|
||||
XCTAssertEqualObjects(element.lastChildNode.previousSibling, firstChild);
|
||||
XCTAssertEqualObjects(element.lastChildNode, secondChild);
|
||||
XCTAssertEqualObjects(element.firstChild, comment);
|
||||
XCTAssertEqualObjects(element.firstChild.nextSibling, firstChild);
|
||||
XCTAssertEqualObjects(element.lastChild.previousSibling, firstChild);
|
||||
XCTAssertEqualObjects(element.lastChild, secondChild);
|
||||
}
|
||||
|
||||
- (void)testParentNode
|
||||
@@ -171,20 +170,20 @@
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
XCTAssertEqualObjects(node.firstChiledNode, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChildNode, firstChild);
|
||||
XCTAssertEqualObjects(node.firstChild, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChild, firstChild);
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
XCTAssertEqualObjects(node.firstChiledNode, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChildNode, secondChild);
|
||||
XCTAssertEqualObjects(node.firstChild, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChild, secondChild);
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
XCTAssertEqualObjects(node.firstChiledNode, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChildNode, thirdChild);
|
||||
XCTAssertEqualObjects(node.firstChild, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChild, thirdChild);
|
||||
}
|
||||
|
||||
- (void)testNextAndPreviousSiblingNodes
|
||||
@@ -470,4 +469,17 @@
|
||||
XCTAssertEqualObjects(thirdChild.parentNode, newParent);
|
||||
}
|
||||
|
||||
- (void)testElementSetInnerHTML
|
||||
{
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
[element appendNode:[[HTMLElement alloc] initWithTagName:@"img"]];
|
||||
|
||||
[element setInnerHTML:@"<p></p><p></p>"];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 2);
|
||||
|
||||
XCTAssertEqualObjects(element.firstChild.asElement.tagName, @"p");
|
||||
XCTAssertEqualObjects([element childNodeAtIndex:1].asElement.tagName, @"p");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
@implementation HTMLKitParserPerformance
|
||||
|
||||
#define HTMLKIT_NO_DOM_CHECKS
|
||||
|
||||
- (void)testParserPerformance
|
||||
{
|
||||
NSString *path = [[NSBundle bundleForClass:self.class] resourcePath];
|
||||
@@ -28,4 +30,6 @@
|
||||
}];
|
||||
}
|
||||
|
||||
#undef HTMLKIT_NO_DOM_CHECKS
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "HTML5LibTreeConstructionTest.h"
|
||||
#import "HTMLNodes.h"
|
||||
#import "HTMLDOM.h"
|
||||
#import "HTMLParser.h"
|
||||
|
||||
|
||||
@@ -121,14 +121,14 @@
|
||||
{
|
||||
XCTAssertEqualObjects(actual.name, expected.name, @"Node name mismatch [%@ should be %@]:\n%@",
|
||||
actual.name, expected.name, message);
|
||||
XCTAssert(actual.type == expected.type, @"Node type mismatch [%hd should be %hd]:\n%@",
|
||||
actual.type, expected.type, message);
|
||||
XCTAssert(actual.nodeType == expected.nodeType, @"Node type mismatch [%hd should be %hd]:\n%@",
|
||||
actual.nodeType, expected.nodeType, message);
|
||||
|
||||
if (actual.type != expected.type) {
|
||||
if (actual.nodeType != expected.nodeType) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (actual.type) {
|
||||
switch (actual.nodeType) {
|
||||
case HTMLNodeDocumentType:
|
||||
XCTAssertEqualObjects([(HTMLDocumentType *)actual publicIdentifier], [(HTMLDocumentType *)expected publicIdentifier], @"%@", message);
|
||||
XCTAssertEqualObjects([(HTMLDocumentType *)actual systemIdentifier], [(HTMLDocumentType *)expected systemIdentifier], @"%@", message);
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
//
|
||||
// HTMLTreeWalkerTests.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 05/06/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "HTMLTreeWalker.h"
|
||||
#import "HTMLDOM.h"
|
||||
|
||||
@interface HTMLTreeWalkerTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation HTMLTreeWalkerTests
|
||||
|
||||
#pragma mark - Asserts
|
||||
|
||||
#define AssertElementWithId(input, id) \
|
||||
do { \
|
||||
HTMLNode *node = input;\
|
||||
XCTAssertEqual(node.nodeType, HTMLNodeElement);\
|
||||
XCTAssertEqualObjects(node.asElement[@"id"], id);\
|
||||
} while(0)
|
||||
|
||||
#define AssertTextWithValue(input, value) \
|
||||
do { \
|
||||
HTMLNode *node = input;\
|
||||
XCTAssertEqual(node.nodeType, HTMLNodeText);\
|
||||
XCTAssertEqualObjects(node.textContent, value);\
|
||||
} while(0)
|
||||
|
||||
#define AssertCommentWithValue(input, value) \
|
||||
do { \
|
||||
HTMLNode *node = input;\
|
||||
XCTAssertEqual(node.nodeType, HTMLNodeComment);\
|
||||
XCTAssertEqualObjects(node.textContent, value);\
|
||||
} while(0)
|
||||
|
||||
#pragma mark - Tests
|
||||
|
||||
- (void)testTreeWalkerInit
|
||||
{
|
||||
HTMLNode *root = self.basicWalkingDOM;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root];
|
||||
|
||||
XCTAssertNotNil(walker);
|
||||
XCTAssertNotNil(walker.root);
|
||||
XCTAssertNotNil(walker.currentNode);
|
||||
XCTAssertNil(walker.filter);
|
||||
XCTAssertEqual(walker.whatToShow, HTMLNodeFilterShowAll);
|
||||
|
||||
XCTAssertEqualObjects(walker.root, root);
|
||||
XCTAssertEqualObjects(walker.root, walker.currentNode);
|
||||
}
|
||||
|
||||
#pragma mark - Basic Walking
|
||||
|
||||
- (HTMLNode *)basicWalkingDOM
|
||||
{
|
||||
// Tree structure:
|
||||
// #a
|
||||
// |
|
||||
// +----+----+
|
||||
// | |
|
||||
// "b" #c
|
||||
// |
|
||||
// +----+----+
|
||||
// | |
|
||||
// #d <!--j-->
|
||||
// |
|
||||
// +----+----+
|
||||
// | | |
|
||||
// "e" #f "i"
|
||||
// |
|
||||
// +--+--+
|
||||
// | |
|
||||
// "g" <!--h-->
|
||||
|
||||
HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"a"}];
|
||||
|
||||
[div appendNode:[[HTMLText alloc] initWithData:@"b"]];
|
||||
|
||||
HTMLElement *c = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"c"}];
|
||||
[div appendNode:c];
|
||||
|
||||
HTMLElement *d = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"d"}];
|
||||
[c appendNode:d];
|
||||
[c appendNode:[[HTMLComment alloc] initWithData:@"j"]];
|
||||
|
||||
[d appendNode:[[HTMLText alloc] initWithData:@"e"]];
|
||||
|
||||
HTMLElement *f = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"f"}];
|
||||
[d appendNode:f];
|
||||
[d appendNode:[[HTMLText alloc] initWithData:@"i"]];
|
||||
|
||||
[f appendNode:[[HTMLText alloc] initWithData:@"g"]];
|
||||
[f appendNode:[[HTMLComment alloc] initWithData:@"h"]];
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
- (void)testBasicWalking
|
||||
{
|
||||
HTMLNode *root = self.basicWalkingDOM;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root];
|
||||
|
||||
HTMLNode *f = root.lastChild.firstChild.childNodes[1];
|
||||
|
||||
AssertElementWithId(walker.currentNode, @"a");
|
||||
XCTAssertNil(walker.parentNode);
|
||||
AssertElementWithId(walker.currentNode, @"a");
|
||||
|
||||
AssertTextWithValue(walker.firstChild, @"b");
|
||||
AssertTextWithValue(walker.currentNode, @"b");
|
||||
|
||||
AssertElementWithId(walker.nextSibling, @"c");
|
||||
AssertElementWithId(walker.currentNode, @"c");
|
||||
|
||||
AssertCommentWithValue(walker.lastChild, @"j");
|
||||
AssertCommentWithValue(walker.currentNode, @"j");
|
||||
|
||||
AssertElementWithId(walker.previousSibling, @"d");
|
||||
AssertElementWithId(walker.currentNode, @"d");
|
||||
|
||||
AssertTextWithValue(walker.nextNode, @"e");
|
||||
AssertTextWithValue(walker.currentNode, @"e");
|
||||
|
||||
AssertElementWithId(walker.parentNode, @"d");
|
||||
AssertElementWithId(walker.currentNode, @"d");
|
||||
|
||||
AssertElementWithId(walker.previousNode, @"c");
|
||||
AssertElementWithId(walker.currentNode, @"c");
|
||||
|
||||
XCTAssertNil(walker.nextSibling);
|
||||
AssertElementWithId(walker.currentNode, @"c");
|
||||
|
||||
walker.currentNode = f;
|
||||
XCTAssertEqualObjects(walker.currentNode, f);
|
||||
}
|
||||
|
||||
#pragma mark - Current Node
|
||||
|
||||
- (HTMLDocument *)currentNodeDOM
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument documentWithString:
|
||||
@"<div id='first'><p><a></a></p></div>"
|
||||
@"<div id='second'><p><b></b></p</div>"];
|
||||
|
||||
return document;
|
||||
}
|
||||
|
||||
- (void)testThatTreeWalkerParentHasNoEffectCurrentNodeWhenParentIsNotUnderRoot
|
||||
{
|
||||
HTMLDocument *document = self.currentNodeDOM;
|
||||
HTMLNode *first = document.body.firstChild;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:first
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:nil];
|
||||
|
||||
AssertElementWithId(walker.currentNode, @"first");
|
||||
XCTAssertNil(walker.parentNode);
|
||||
AssertElementWithId(walker.currentNode, @"first");
|
||||
}
|
||||
|
||||
- (void)testThatSettingCurrentNodeToNodesNotUnderRootIsHandledCorrectly
|
||||
{
|
||||
HTMLDocument *document = self.currentNodeDOM;
|
||||
HTMLNode *first = document.body.firstChild;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:first
|
||||
showOptions:HTMLNodeFilterShowElement|HTMLNodeFilterShowComment
|
||||
filter:nil];
|
||||
walker.currentNode = document.documentElement;
|
||||
XCTAssertNil(walker.parentNode);
|
||||
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
|
||||
|
||||
walker.currentNode = document.documentElement;
|
||||
XCTAssertEqualObjects(walker.nextNode, document.documentElement.firstChild);
|
||||
XCTAssertEqualObjects(walker.currentNode, document.documentElement.firstChild);
|
||||
|
||||
walker.currentNode = document.documentElement;
|
||||
XCTAssertNil(walker.previousNode);
|
||||
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
|
||||
|
||||
walker.currentNode = document.documentElement;
|
||||
XCTAssertEqualObjects(walker.firstChild, document.documentElement.firstChild);
|
||||
XCTAssertEqualObjects(walker.currentNode, document.documentElement.firstChild);
|
||||
|
||||
walker.currentNode = document.documentElement;
|
||||
XCTAssertEqualObjects(walker.lastChild, document.documentElement.lastChild);
|
||||
XCTAssertEqualObjects(walker.currentNode, document.documentElement.lastChild);
|
||||
|
||||
walker.currentNode = document.documentElement;
|
||||
XCTAssertNil(walker.nextSibling);
|
||||
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
|
||||
|
||||
walker.currentNode = document.documentElement;
|
||||
XCTAssertNil(walker.previousSibling);
|
||||
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
|
||||
}
|
||||
|
||||
#pragma mark - Filter
|
||||
|
||||
- (HTMLElement *)filterBasicDOM
|
||||
{
|
||||
HTMLElement *root = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"root"}];
|
||||
|
||||
HTMLElement *a1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"A1"}];
|
||||
HTMLElement *b1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B1"}];
|
||||
HTMLElement *b2 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B2"}];
|
||||
|
||||
[root appendNode:a1];
|
||||
[a1 appendNode:b1];
|
||||
[a1 appendNode:b2];
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
- (void)testTreeWalkerNilFilter
|
||||
{
|
||||
HTMLElement *root = self.filterBasicDOM;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:nil];
|
||||
|
||||
AssertElementWithId(walker.currentNode, @"root");
|
||||
AssertElementWithId(walker.firstChild, @"A1");
|
||||
AssertElementWithId(walker.currentNode, @"A1");
|
||||
AssertElementWithId(walker.nextNode, @"B1");
|
||||
AssertElementWithId(walker.currentNode, @"B1");
|
||||
}
|
||||
|
||||
- (void)testTreeWalkerWithFilter
|
||||
{
|
||||
HTMLElement *root = self.filterBasicDOM;
|
||||
|
||||
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
|
||||
if ([node.asElement[@"id"] isEqualToString:@"B1"]) {
|
||||
return HTMLNodeFilterSkip;
|
||||
}
|
||||
return HTMLNodeFilterAccept;
|
||||
}];
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
AssertElementWithId(walker.currentNode, @"root");
|
||||
AssertElementWithId(walker.firstChild, @"A1");
|
||||
AssertElementWithId(walker.currentNode, @"A1");
|
||||
AssertElementWithId(walker.nextNode, @"B2");
|
||||
AssertElementWithId(walker.currentNode, @"B2");
|
||||
}
|
||||
|
||||
#pragma mark - Filter Skip
|
||||
|
||||
- (HTMLElement *)filterDOM
|
||||
{
|
||||
HTMLElement *root = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"root"}];
|
||||
|
||||
HTMLElement *a1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"A1"}];
|
||||
HTMLElement *b1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B1"}];
|
||||
HTMLElement *b2 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B2"}];
|
||||
HTMLElement *b3 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B3"}];
|
||||
HTMLElement *c1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"C1"}];
|
||||
|
||||
[root appendNode:a1];
|
||||
[a1 appendNode:b1];
|
||||
[a1 appendNode:b2];
|
||||
[a1 appendNode:b3];
|
||||
[b1 appendNode:c1];
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
- (id<HTMLNodeFilter>)skipB1Filter
|
||||
{
|
||||
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
|
||||
if ([node.asElement[@"id"] isEqualToString:@"B1"]) {
|
||||
return HTMLNodeFilterSkip;
|
||||
}
|
||||
return HTMLNodeFilterAccept;
|
||||
}];
|
||||
return filter;
|
||||
}
|
||||
|
||||
- (id<HTMLNodeFilter>)skipB2Filter
|
||||
{
|
||||
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
|
||||
if ([node.asElement[@"id"] isEqualToString:@"B2"]) {
|
||||
return HTMLNodeFilterSkip;
|
||||
}
|
||||
return HTMLNodeFilterAccept;
|
||||
}];
|
||||
return filter;
|
||||
}
|
||||
|
||||
- (id<HTMLNodeFilter>)rejectB1Filter
|
||||
{
|
||||
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
|
||||
if ([node.asElement[@"id"] isEqualToString:@"B1"]) {
|
||||
return HTMLNodeFilterReject;
|
||||
}
|
||||
return HTMLNodeFilterAccept;
|
||||
}];
|
||||
return filter;
|
||||
}
|
||||
|
||||
- (id<HTMLNodeFilter>)rejectB2Filter
|
||||
{
|
||||
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
|
||||
if ([node.asElement[@"id"] isEqualToString:@"B2"]) {
|
||||
return HTMLNodeFilterReject;
|
||||
}
|
||||
return HTMLNodeFilterAccept;
|
||||
}];
|
||||
return filter;
|
||||
}
|
||||
|
||||
static HTMLElement * (^ FindElementById)(HTMLNode *, NSString *) = ^ HTMLElement * (HTMLNode *root, NSString *id) {
|
||||
for (HTMLNode *node in [root nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]) {
|
||||
if ([node.asElement[@"id"] isEqualToString:id]) {
|
||||
return node.asElement;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
};
|
||||
|
||||
- (void)testThatFilterSkipsNextNode
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.skipB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
AssertElementWithId(walker.nextNode, @"A1");
|
||||
AssertElementWithId(walker.nextNode, @"C1");
|
||||
AssertElementWithId(walker.nextNode, @"B2");
|
||||
AssertElementWithId(walker.nextNode, @"B3");
|
||||
}
|
||||
|
||||
- (void)testThatFilterSkipsFirstChild
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.skipB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
AssertElementWithId(walker.firstChild, @"A1");
|
||||
AssertElementWithId(walker.firstChild, @"C1");
|
||||
}
|
||||
|
||||
- (void)testThatFilterSkipsNextSibling
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.skipB2Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
AssertElementWithId(walker.firstChild, @"A1");
|
||||
AssertElementWithId(walker.firstChild, @"B1");
|
||||
AssertElementWithId(walker.nextSibling, @"B3");
|
||||
}
|
||||
|
||||
- (void)testThatFilterSkipsParentNode
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.skipB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
walker.currentNode = FindElementById(root, @"C1");
|
||||
AssertElementWithId(walker.parentNode, @"A1");
|
||||
}
|
||||
|
||||
- (void)testThatFilterSkipsPreviousSibling
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.skipB2Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
walker.currentNode = FindElementById(root, @"B3");
|
||||
AssertElementWithId(walker.previousSibling, @"B1");
|
||||
}
|
||||
|
||||
- (void)testThatFilterSkipsPreviousNode
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.skipB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
walker.currentNode = FindElementById(root, @"B3");
|
||||
AssertElementWithId(walker.previousNode, @"B2");
|
||||
AssertElementWithId(walker.previousNode, @"C1");
|
||||
AssertElementWithId(walker.previousNode, @"A1");
|
||||
}
|
||||
|
||||
#pragma mark - Filter Reject
|
||||
|
||||
- (void)testThatFilterRejectsNextNode
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.rejectB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
AssertElementWithId(walker.nextNode, @"A1");
|
||||
AssertElementWithId(walker.nextNode, @"B2");
|
||||
AssertElementWithId(walker.nextNode, @"B3");
|
||||
}
|
||||
|
||||
- (void)testThatFilterRejectsFirstChild
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.rejectB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
AssertElementWithId(walker.firstChild, @"A1");
|
||||
AssertElementWithId(walker.firstChild, @"B2");
|
||||
}
|
||||
|
||||
- (void)testThatFilterRejectsNextSibling
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.rejectB2Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
AssertElementWithId(walker.firstChild, @"A1");
|
||||
AssertElementWithId(walker.firstChild, @"B1");
|
||||
AssertElementWithId(walker.nextSibling, @"B3");
|
||||
}
|
||||
|
||||
- (void)testThatFilterRejectsParentNode
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.rejectB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
walker.currentNode = FindElementById(root, @"C1");
|
||||
AssertElementWithId(walker.parentNode, @"A1");
|
||||
}
|
||||
|
||||
- (void)testThatFilterRejectsPreviousSibling
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.rejectB2Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
walker.currentNode = FindElementById(root, @"B3");
|
||||
AssertElementWithId(walker.previousSibling, @"B1");
|
||||
}
|
||||
|
||||
- (void)testThatFilterRejectsPreviousNode
|
||||
{
|
||||
HTMLElement *root = self.filterDOM;
|
||||
id<HTMLNodeFilter> filter = self.rejectB1Filter;
|
||||
|
||||
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
|
||||
showOptions:HTMLNodeFilterShowElement
|
||||
filter:filter];
|
||||
|
||||
walker.currentNode = FindElementById(root, @"B3");
|
||||
AssertElementWithId(walker.previousNode, @"B2");
|
||||
AssertElementWithId(walker.previousNode, @"A1");
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user