Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0401118657 | |||
| 045e4db9d1 | |||
| a7caa34762 | |||
| df53870880 | |||
| 7f25aacaf1 | |||
| 5e482788ce | |||
| a39890e6e9 | |||
| fd516c67ef | |||
| a390edf599 | |||
| 0c82f6891b | |||
| 0d7c57d755 | |||
| 40400864d8 | |||
| dc3de7a470 | |||
| c1b18f527c | |||
| d4bb3c6636 | |||
| 0baa343e95 | |||
| 2f1555e93d | |||
| a0fd89f417 | |||
| d002c6cedd | |||
| 71fefa2fa9 | |||
| 066bdeffa8 | |||
| 3df5a219e1 | |||
| e1c3533a1c | |||
| dfeebc7f7f | |||
| cd6e8bf4fc | |||
| 0fa394b911 | |||
| 13ed63017e | |||
| ac561570f3 | |||
| 165cdb5a75 | |||
| aece7138a4 | |||
| 45156d98fd | |||
| 7892a925c8 | |||
| f8ee4a38b4 | |||
| de597a51a4 | |||
| 470b9b8d37 | |||
| 915f4cc064 | |||
| 11af0509a3 | |||
| 2ee3b2d2b3 | |||
| 1e9118078f | |||
| 74aec57785 | |||
| 111acb4f8f | |||
| 2c9f68e2ea | |||
| 3d3e4d52b4 | |||
| bf061d6367 | |||
| 40baea8ece | |||
| a2c6f22495 | |||
| b2f1864c80 | |||
| cffe1cc703 | |||
| bc6bbf1d63 | |||
| 71aed89574 | |||
| 36960dceb3 | |||
| 3ddfa15b15 | |||
| 071742fb27 | |||
| 1bc896efc9 | |||
| 429f00adb6 | |||
| d08ac2100e | |||
| 62a6336dce |
@@ -49,14 +49,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 */; };
|
||||
@@ -69,6 +66,20 @@
|
||||
624493AC19CD0CBE00BCDDF4 /* HTMLToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */; };
|
||||
624493AD19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */; };
|
||||
624493AE19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */; };
|
||||
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 */; };
|
||||
@@ -80,6 +91,8 @@
|
||||
624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; };
|
||||
624B9FB51AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; };
|
||||
624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; };
|
||||
624FC37A1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */; };
|
||||
624FC37B1AE591D80015DDF9 /* HTMLKitNodesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */; };
|
||||
625A14B019C7829400AD0C32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14AF19C7829400AD0C32 /* Cocoa.framework */; };
|
||||
625A14BA19C7829400AD0C32 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 625A14B819C7829400AD0C32 /* InfoPlist.strings */; };
|
||||
625A14BE19C7829400AD0C32 /* HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 625A14BD19C7829400AD0C32 /* HTMLKit.m */; };
|
||||
@@ -116,6 +129,16 @@
|
||||
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 /* 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 */; };
|
||||
62D89DB41AE7081600B6243D /* HTMLElementTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */; };
|
||||
62D89DB51AE7081600B6243D /* HTMLElementAdjustment.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234C3361AB3BF710046F527 /* HTMLElementAdjustment.h */; };
|
||||
62D89DB61AE7081600B6243D /* HTMLParserInsertionModes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */; };
|
||||
62D89DB71AE7081600B6243D /* HTMLQuirksMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 623719431AA12EE8002E03C8 /* HTMLQuirksMode.h */; };
|
||||
62EC7AE61AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; };
|
||||
62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */; };
|
||||
62F31FDD19E9DCCF007F0657 /* HTMLTokenizerEntities.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */; };
|
||||
62F31FDE19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */; };
|
||||
62F31FDF19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */; };
|
||||
@@ -173,7 +196,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>"; };
|
||||
@@ -186,11 +209,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>"; };
|
||||
@@ -200,12 +221,22 @@
|
||||
624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerStates.h; sourceTree = "<group>"; };
|
||||
624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLToken.h; sourceTree = "<group>"; };
|
||||
624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLToken.m; 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>"; };
|
||||
624AC90D19FC702E00BD3C4A /* HTML Standard.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "HTML Standard.html"; sourceTree = "<group>"; };
|
||||
624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitStringCategoryTests.m; sourceTree = "<group>"; };
|
||||
624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitOrderedDictionaryTests.m; sourceTree = "<group>"; };
|
||||
624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodesTests.m; sourceTree = "<group>"; };
|
||||
625A14AC19C7829400AD0C32 /* HTMLKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTMLKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
625A14AF19C7829400AD0C32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
625A14B219C7829400AD0C32 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
@@ -242,6 +273,7 @@
|
||||
62D8345719FB1AC4009205A9 /* HTML5LibTokenizerTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5LibTokenizerTest.h; sourceTree = "<group>"; };
|
||||
62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTokenizerTest.m; sourceTree = "<group>"; };
|
||||
62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerCharacters.h; sourceTree = "<group>"; };
|
||||
62EC7AE51AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitMutationAlgorithmsTests.m; sourceTree = "<group>"; };
|
||||
62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerEntities.h; sourceTree = "<group>"; };
|
||||
62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTokenizerEntities.m; sourceTree = "<group>"; };
|
||||
62F873E919E088C90062683C /* HTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLParser.h; sourceTree = "<group>"; };
|
||||
@@ -299,31 +331,40 @@
|
||||
name = Tokenizer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
623719441AA1472B002E03C8 /* Nodes */ = {
|
||||
623719441AA1472B002E03C8 /* DOM */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
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 */ = {
|
||||
@@ -337,13 +378,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 */ = {
|
||||
@@ -354,6 +397,14 @@
|
||||
name = Categories;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
624E1A2D1B1D1C8A00E66AAC /* Structures */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */,
|
||||
);
|
||||
name = Structures;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
625A14A219C7829400AD0C32 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -401,11 +452,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 */,
|
||||
625A14B619C7829400AD0C32 /* Supporting Files */,
|
||||
@@ -429,8 +478,9 @@
|
||||
children = (
|
||||
6236738C1AC0CD2400FF89B3 /* Tokenizer */,
|
||||
623975581AC362A5007E26F1 /* Tree Construction */,
|
||||
624B9FB71AE072CB00646C4C /* Nodes */,
|
||||
624B9FB71AE072CB00646C4C /* DOM */,
|
||||
624B9FB81AE072D500646C4C /* Categories */,
|
||||
624E1A2D1B1D1C8A00E66AAC /* Structures */,
|
||||
625A14CB19C7829400AD0C32 /* Supporting Files */,
|
||||
);
|
||||
name = Tests;
|
||||
@@ -457,7 +507,6 @@
|
||||
6234BEED1AABBF1400DEB15F /* HTMLStackOfOpenElements.m */,
|
||||
62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */,
|
||||
62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */,
|
||||
628B7CE61A080E1000602C87 /* HTMLNamespaces.h */,
|
||||
6223211D1A969B9300BACED5 /* HTMLElementTypes.h */,
|
||||
6234C3361AB3BF710046F527 /* HTMLElementAdjustment.h */,
|
||||
6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */,
|
||||
@@ -522,24 +571,34 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
624717181B22333200C11912 /* HTMLNodeTraversal.h in Headers */,
|
||||
6235CE9B1AA509430026937B /* NSString+HTMLKit.h in Headers */,
|
||||
62D89DB11AE7081600B6243D /* HTMLTokenizerStates.h in Headers */,
|
||||
62D89DB21AE7081600B6243D /* HTMLTokenizerCharacters.h in Headers */,
|
||||
62D89DB31AE7081600B6243D /* HTMLNamespaces.h in Headers */,
|
||||
62D89DB41AE7081600B6243D /* HTMLElementTypes.h in Headers */,
|
||||
62D89DB51AE7081600B6243D /* HTMLElementAdjustment.h in Headers */,
|
||||
62D89DB61AE7081600B6243D /* HTMLParserInsertionModes.h in Headers */,
|
||||
62D89DB71AE7081600B6243D /* HTMLQuirksMode.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 */,
|
||||
62F31FDD19E9DCCF007F0657 /* HTMLTokenizerEntities.h in Headers */,
|
||||
623406E11ADB04F9004677A3 /* HTMLTemplate.h in Headers */,
|
||||
6234BEEE1AABBF1400DEB15F /* HTMLStackOfOpenElements.h in Headers */,
|
||||
6238C9851AB8D6330006512E /* HTMLKitExceptions.h in Headers */,
|
||||
6238C9851AB8D6330006512E /* HTMLKitDOMExceptions.h in Headers */,
|
||||
6238039F1AB63A8C008A53D0 /* HTMLEOFToken.h in Headers */,
|
||||
6279F87419E1808D00F12EE5 /* HTMLElement.h in Headers */,
|
||||
62AE593F19F9907C0043F069 /* HTMLTagToken.h in Headers */,
|
||||
623857911A9E772B003A45D9 /* HTMLDocument.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 */,
|
||||
@@ -548,6 +607,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 */,
|
||||
);
|
||||
@@ -701,24 +761,27 @@
|
||||
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 */,
|
||||
6279F87619E1808D00F12EE5 /* HTMLElement.m in Sources */,
|
||||
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 */,
|
||||
625A14BE19C7829400AD0C32 /* HTMLKit.m in Sources */,
|
||||
623857981A9E8606003A45D9 /* HTMLDocumentType.m in Sources */,
|
||||
@@ -735,13 +798,16 @@
|
||||
files = (
|
||||
6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */,
|
||||
623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */,
|
||||
6247171D1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */,
|
||||
62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */,
|
||||
624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */,
|
||||
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 */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -751,24 +817,27 @@
|
||||
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 */,
|
||||
6279F87519E1808D00F12EE5 /* HTMLElement.m in Sources */,
|
||||
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 */,
|
||||
625A150219C783DE00AD0C32 /* HTMLKit.m in Sources */,
|
||||
623857971A9E8606003A45D9 /* HTMLDocumentType.m in Sources */,
|
||||
@@ -785,13 +854,16 @@
|
||||
files = (
|
||||
6239755A1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */,
|
||||
623CAF9D1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */,
|
||||
6247171C1B2240B800C11912 /* HTMLTreeWalkerTests.m in Sources */,
|
||||
62EC7AE61AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */,
|
||||
624B9FB51AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */,
|
||||
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 */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1008,7 +1080,6 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
@@ -1032,7 +1103,6 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
"$(DEVELOPER_FRAMEWORKS_DIR)",
|
||||
);
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
|
||||
@implementation HTMLComment
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithData:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithData:(NSString *)data
|
||||
{
|
||||
self = [super initWithName:@"#comment" type:HTMLNodeComment];
|
||||
|
||||
@@ -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)];
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
|
||||
@implementation HTMLDocumentFragment
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithDocument:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDocument:(HTMLDocument *)document
|
||||
{
|
||||
self = [super initWithName:@"#document-fragment" type:HTMLNodeDocumentFragment];
|
||||
@@ -28,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]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ NS_INLINE BOOL nilOrEqual(id first, id second) {
|
||||
|
||||
@implementation HTMLDocumentType
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
return [self initWithName:@"html" publicIdentifier:nil systemIdentifier:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithName:(NSString *)name
|
||||
publicIdentifier:(NSString *)publicIdentifier
|
||||
systemIdentifier:(NSString *)systemIdentifier
|
||||
|
||||
@@ -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";
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
if (node.htmlNamespace == element.htmlNamespace &&
|
||||
[node.tagName isEqualToString:element.tagName] &&
|
||||
[node.attributes isEqualTo:element.attributes]) {
|
||||
[node.attributes isEqual:element.attributes]) {
|
||||
existing++;
|
||||
}
|
||||
if (existing == 3) {
|
||||
|
||||
+40
-12
@@ -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,8 +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;
|
||||
@@ -65,16 +83,22 @@ typedef NS_ENUM(short, HTMLNodeType)
|
||||
|
||||
- (NSUInteger)indexOfChildNode:(HTMLNode *)node;
|
||||
|
||||
- (HTMLNode *)insertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child;
|
||||
- (HTMLNode *)prependNode:(HTMLNode *)node;
|
||||
|
||||
- (void)prependNodes:(NSArray *)nodes;
|
||||
|
||||
- (HTMLNode *)appendNode:(HTMLNode *)node;
|
||||
|
||||
- (void)appendNodes:(NSArray *)nodes;
|
||||
|
||||
- (HTMLNode *)insertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child;
|
||||
|
||||
- (HTMLNode *)replaceChildNode:(HTMLNode *)node withNode:(HTMLNode *)replacement;
|
||||
|
||||
- (void)replaceAllChildNodesWithNode:(HTMLNode *)node;
|
||||
|
||||
- (void)removeFromParentNode;
|
||||
|
||||
- (HTMLNode *)removeChildNode:(HTMLNode *)node;
|
||||
|
||||
- (HTMLNode *)removeChildNodeAtIndex:(NSUInteger)index;
|
||||
@@ -83,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;
|
||||
|
||||
|
||||
+238
-94
@@ -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;
|
||||
}
|
||||
@@ -139,35 +145,65 @@
|
||||
return [self.childNodes indexOfObject:node];
|
||||
}
|
||||
|
||||
- (HTMLNode *)insertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child
|
||||
- (HTMLNode *)prependNode:(HTMLNode *)node
|
||||
{
|
||||
node = [self preInsertNode:node beforeChildNode:child];
|
||||
node.parentNode = self;
|
||||
return node;
|
||||
return [self insertNode:node beforeChildNode:self.firstChild];
|
||||
}
|
||||
|
||||
- (void)prependNodes:(NSArray *)nodes
|
||||
{
|
||||
for (id node in nodes.reverseObjectEnumerator) {
|
||||
[self insertNode:node beforeChildNode:self.firstChild];
|
||||
}
|
||||
}
|
||||
|
||||
- (HTMLNode *)appendNode:(HTMLNode *)node
|
||||
{
|
||||
node = [self preInsertNode:node beforeChildNode:nil];
|
||||
node.parentNode = self;
|
||||
return node;
|
||||
return [self insertNode:node beforeChildNode:nil];
|
||||
}
|
||||
|
||||
- (void)appendNodes:(NSArray *)nodes
|
||||
{
|
||||
for (id node in nodes) {
|
||||
[self appendNode:node];
|
||||
[self insertNode:node beforeChildNode:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (HTMLNode *)insertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child
|
||||
{
|
||||
#ifndef HTMLKIT_NO_DOM_CHECKS
|
||||
[self ensurePreInsertionValidityOfNode:node beforeChildNode:child];
|
||||
#endif
|
||||
|
||||
[self.ownerDocument adoptNode:node];
|
||||
|
||||
NSArray *nodes = node.nodeType == HTMLNodeDocumentFragment ? [NSArray arrayWithArray: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 (node.nodeType == HTMLNodeDocumentFragment) {
|
||||
[node removeAllChildNodes];
|
||||
}
|
||||
|
||||
[nodes makeObjectsPerformSelector:@selector(setParentNode:) withObject:self];
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
- (HTMLNode *)replaceChildNode:(HTMLNode *)child withNode:(HTMLNode *)node
|
||||
{
|
||||
#ifndef HTMLKIT_NO_DOM_CHECKS
|
||||
[self ensureReplacementValidityOfChildNode:child withNode:node];
|
||||
#endif
|
||||
|
||||
[self.ownerDocument adoptNode:node];
|
||||
NSUInteger index = [self indexOfChildNode:child];
|
||||
node.parentNode = self;
|
||||
[(NSMutableOrderedSet *)self.childNodes replaceObjectAtIndex:index withObject:node];
|
||||
[self insertNode:node beforeChildNode:child];
|
||||
[child removeFromParentNode];
|
||||
return child;
|
||||
}
|
||||
|
||||
@@ -181,6 +217,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeFromParentNode
|
||||
{
|
||||
[self.parentNode removeChildNode:self];
|
||||
}
|
||||
|
||||
- (HTMLNode *)removeChildNode:(HTMLNode *)child
|
||||
{
|
||||
if (child.parentNode != self) {
|
||||
@@ -189,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;
|
||||
}
|
||||
|
||||
@@ -205,14 +254,95 @@
|
||||
for (HTMLNode *child in self.childNodes.array) {
|
||||
[node appendNode:child];
|
||||
}
|
||||
[self removeAllChildNodes];
|
||||
[(NSMutableOrderedSet *)self.childNodes removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)removeAllChildNodes
|
||||
{
|
||||
[self.childNodes.array makeObjectsPerformSelector:@selector(setParentNode:) withObject:nil];
|
||||
[(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
|
||||
@@ -226,40 +356,48 @@
|
||||
}];
|
||||
}
|
||||
|
||||
- (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];
|
||||
}
|
||||
|
||||
#pragma mark - Mutation Algorithms
|
||||
|
||||
- (HTMLNode *)preInsertNode:(HTMLNode *)node beforeChildNode:(HTMLNode *)child
|
||||
{
|
||||
[self ensurePreInsertionValidityOfNode:node beforeChildNode:child];
|
||||
[self.ownerDocument adoptNode:node];
|
||||
NSUInteger index = [self indexOfChildNode:child];
|
||||
if (index != NSNotFound) {
|
||||
[(NSMutableOrderedSet *)self.childNodes insertObject:node atIndex:index];
|
||||
} else {
|
||||
[(NSMutableOrderedSet *)self.childNodes addObject:node];
|
||||
if (block == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
return node;
|
||||
[self.childNodes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
|
||||
if ([obj isKindOfClass:[HTMLElement class]]) {
|
||||
block([obj asElement], idx, stop);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
NS_INLINE void CheckParentValid(HTMLNode *node, NSString *cmd)
|
||||
- (HTMLNodeIterator *)nodeIterator
|
||||
{
|
||||
if (node.type != HTMLNodeDocument &&
|
||||
node.type != HTMLNodeDocumentFragment &&
|
||||
node.type != HTMLNodeElement) {
|
||||
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
|
||||
|
||||
#pragma mark - Validity Checks
|
||||
|
||||
NS_INLINE void CheckParentValid(HTMLNode *parent, NSString *cmd)
|
||||
{
|
||||
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, node.name];
|
||||
cmd, parent.name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,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];
|
||||
@@ -288,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];
|
||||
@@ -313,28 +451,28 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
|
||||
void (^ hierarchyError)() = ^{
|
||||
[NSException raise:HTMLKitHierarchyRequestError
|
||||
format:@"%@: Hierarchy Request Error. The operation would yield an incorrect node tree.",
|
||||
NSStringFromSelector(_cmd)];
|
||||
format:@"%@: Hierarchy Request Error, inserting (%@) into (%@). The operation would yield an incorrect node tree.",
|
||||
NSStringFromSelector(_cmd), self, node];
|
||||
};
|
||||
|
||||
if (self.type == HTMLNodeDocument) {
|
||||
switch (node.type) {
|
||||
if (self.nodeType == HTMLNodeDocument) {
|
||||
switch (node.nodeType) {
|
||||
case HTMLNodeDocumentFragment:
|
||||
if (self.childNodesCount > 1 ||
|
||||
[self hasChildNodeOfType:HTMLNodeText]) {
|
||||
if (node.childNodesCount > 1 ||
|
||||
[node hasChildNodeOfType:HTMLNodeText]) {
|
||||
hierarchyError();
|
||||
} else if (self.childNodesCount == 1) {
|
||||
if (self.hasChildNodes ||
|
||||
child.type == HTMLNodeDocumentType ||
|
||||
child.nextSibling.type == HTMLNodeDocumentType) {
|
||||
} else if (node.childNodesCount == 1) {
|
||||
if ([self hasChildNodeOfType:HTMLNodeElement] ||
|
||||
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;
|
||||
@@ -367,43 +505,42 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
NSStringFromSelector(_cmd)];
|
||||
};
|
||||
|
||||
if (self.type == HTMLNodeDocument) {
|
||||
switch (node.type) {
|
||||
void (^ checkParentHasAnotherChildOfType)(HTMLNodeType) = ^ void (HTMLNodeType type) {
|
||||
[self enumerateChildNodesUsingBlock:^(HTMLNode *node, NSUInteger idx, BOOL *stop) {
|
||||
if (node.nodeType == type && node != child) {
|
||||
*stop = YES;
|
||||
hierarchyError();
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
if (self.nodeType == HTMLNodeDocument) {
|
||||
switch (node.nodeType) {
|
||||
case HTMLNodeDocumentFragment:
|
||||
if (self.childNodesCount > 1 ||
|
||||
[self hasChildNodeOfType:HTMLNodeText]) {
|
||||
if (node.childNodesCount > 1 ||
|
||||
[node hasChildNodeOfType:HTMLNodeText]) {
|
||||
hierarchyError();
|
||||
} else if (self.childNodesCount == 1) {
|
||||
if (self.firstChiledNode != node ||
|
||||
child.nextSibling.type == HTMLNodeDocumentType) {
|
||||
} else if (node.childNodesCount == 1) {
|
||||
if (child.nextSibling.nodeType == HTMLNodeDocumentType) {
|
||||
hierarchyError();
|
||||
}
|
||||
checkParentHasAnotherChildOfType(HTMLNodeElement);
|
||||
}
|
||||
break;
|
||||
case HTMLNodeElement:
|
||||
{
|
||||
if (child.nextSibling.type == HTMLNodeDocumentType) {
|
||||
if (child.nextSibling.nodeType == HTMLNodeDocumentType) {
|
||||
hierarchyError();
|
||||
}
|
||||
[self enumerateChildNodesUsingBlock:^(HTMLNode *node, NSUInteger idx, BOOL *stop) {
|
||||
if (node.type == HTMLNodeElement && node != child) {
|
||||
*stop = YES;
|
||||
hierarchyError();
|
||||
}
|
||||
}];
|
||||
checkParentHasAnotherChildOfType(HTMLNodeElement);
|
||||
break;
|
||||
}
|
||||
case HTMLNodeDocumentType:
|
||||
{
|
||||
if (child.previousSibling.type == HTMLNodeElement) {
|
||||
if (child.previousSibling.nodeType == HTMLNodeElement) {
|
||||
hierarchyError();
|
||||
}
|
||||
[self enumerateChildNodesUsingBlock:^(HTMLNode *node, NSUInteger idx, BOOL *stop) {
|
||||
if (node.type == HTMLNodeDocument && node != child) {
|
||||
*stop = YES;
|
||||
hierarchyError();
|
||||
}
|
||||
}];
|
||||
checkParentHasAnotherChildOfType(HTMLNodeDocumentType);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -412,11 +549,13 @@ NS_INLINE void CheckInvalidCombination(HTMLNode *parent, HTMLNode *node, NSStrin
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (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;
|
||||
}
|
||||
|
||||
@@ -433,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
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// HTMLNodeFilter.h
|
||||
// HTMLKit
|
||||
//
|
||||
// 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>
|
||||
|
||||
- (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"
|
||||
@@ -127,7 +127,7 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([_contextElement isEqualTo:contextElement]) {
|
||||
if ([_contextElement isEqual:contextElement]) {
|
||||
return [_document childNodeAtIndex:0].childNodes.array;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
//
|
||||
// HTMLKitMutationAlgorithmsTests.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 27/04/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "HTMLDOM.h"
|
||||
#import "NSString+HTMLKit.h"
|
||||
|
||||
extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));
|
||||
|
||||
@interface HTMLKitMutationAlgorithmsTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation HTMLKitMutationAlgorithmsTests
|
||||
|
||||
- (void)testValidParentNodeWhenAppending
|
||||
{
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
|
||||
id parent = [HTMLDocument new];
|
||||
XCTAssertNoThrow([parent appendNode:element]);
|
||||
|
||||
parent = [HTMLDocumentFragment new];
|
||||
XCTAssertNoThrow([parent appendNode:element]);
|
||||
|
||||
parent = [HTMLElement new];
|
||||
XCTAssertNoThrow([parent appendNode:element]);
|
||||
|
||||
parent = [HTMLTemplate new];
|
||||
XCTAssertNoThrow([parent appendNode:element]);
|
||||
|
||||
parent = [HTMLDocumentType new];
|
||||
XCTAssertThrows([parent appendNode:element]);
|
||||
|
||||
parent = [HTMLComment new];
|
||||
XCTAssertThrows([parent appendNode:element]);
|
||||
|
||||
parent = [HTMLText new];
|
||||
XCTAssertThrows([parent appendNode:element]);
|
||||
}
|
||||
|
||||
- (void)testValidParentNodeWhenInserting
|
||||
{
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
|
||||
id parent = [HTMLDocument new];
|
||||
XCTAssertNoThrow([parent insertNode:element beforeChildNode:nil]);
|
||||
|
||||
parent = [HTMLDocumentFragment new];
|
||||
XCTAssertNoThrow([parent insertNode:element beforeChildNode:nil]);
|
||||
|
||||
parent = [HTMLElement new];
|
||||
XCTAssertNoThrow([parent insertNode:element beforeChildNode:nil]);
|
||||
|
||||
parent = [HTMLTemplate new];
|
||||
XCTAssertNoThrow([parent insertNode:element beforeChildNode:nil]);
|
||||
|
||||
parent = [HTMLDocumentType new];
|
||||
XCTAssertThrows([parent insertNode:element beforeChildNode:nil]);
|
||||
|
||||
parent = [HTMLComment new];
|
||||
XCTAssertThrows([parent insertNode:element beforeChildNode:nil]);
|
||||
|
||||
parent = [HTMLText new];
|
||||
XCTAssertThrows([parent insertNode:element beforeChildNode:nil]);
|
||||
}
|
||||
|
||||
- (void)testValidChildNodeWhenInserting
|
||||
{
|
||||
HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
HTMLElement *p = [[HTMLElement alloc] initWithTagName:@"p"];
|
||||
[div appendNode:p];
|
||||
|
||||
HTMLElement *table = [[HTMLElement alloc] initWithTagName:@"table"];
|
||||
|
||||
XCTAssertNoThrow([div insertNode:table beforeChildNode:p]);
|
||||
|
||||
[div removeChildNode:p];
|
||||
|
||||
HTMLElement *section = [[HTMLElement alloc] initWithTagName:@"section"];
|
||||
XCTAssertThrows([div insertNode:section beforeChildNode:p]);
|
||||
}
|
||||
|
||||
- (void)testValidChildNodeWhenReplacing
|
||||
{
|
||||
HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
HTMLElement *p = [[HTMLElement alloc] initWithTagName:@"p"];
|
||||
[div appendNode:p];
|
||||
|
||||
HTMLElement *table = [[HTMLElement alloc] initWithTagName:@"table"];
|
||||
|
||||
XCTAssertNoThrow([div replaceChildNode:p withNode:table]);
|
||||
|
||||
XCTAssertThrows([div replaceChildNode:p withNode:[HTMLComment new]]);
|
||||
}
|
||||
|
||||
- (void)testValidChildNodeWhenRemoving
|
||||
{
|
||||
HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
HTMLElement *p = [[HTMLElement alloc] initWithTagName:@"p"];
|
||||
[div appendNode:p];
|
||||
|
||||
XCTAssertNoThrow([div removeChildNode:p]);
|
||||
XCTAssertThrows([div removeChildNode:p]);
|
||||
}
|
||||
|
||||
- (void)testValidInsertedNode
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
|
||||
XCTAssertNoThrow([document appendNode:[HTMLDocumentFragment new]]);
|
||||
XCTAssertNoThrow([document appendNode:[HTMLDocumentType new]]);
|
||||
XCTAssertNoThrow([document appendNode:[HTMLElement new]]);
|
||||
|
||||
HTMLElement *element = [HTMLElement new];
|
||||
|
||||
XCTAssertNoThrow([element appendNode:[HTMLTemplate new]]);
|
||||
XCTAssertNoThrow([element appendNode:[HTMLComment new]]);
|
||||
XCTAssertNoThrow([element appendNode:[HTMLText new]]);
|
||||
}
|
||||
|
||||
- (void)testValidParentForDoctype
|
||||
{
|
||||
HTMLDocumentType *doctype = [HTMLDocumentType new];
|
||||
|
||||
XCTAssertNoThrow([[HTMLDocument new] appendNode:doctype]);
|
||||
|
||||
XCTAssertThrows([[HTMLDocumentFragment new] appendNode:doctype]);
|
||||
XCTAssertThrows([[HTMLDocumentType new] appendNode:doctype]);
|
||||
XCTAssertThrows([[HTMLElement new] appendNode:doctype]);
|
||||
XCTAssertThrows([[HTMLTemplate new] appendNode:doctype]);
|
||||
XCTAssertThrows([[HTMLComment new] appendNode:doctype]);
|
||||
XCTAssertThrows([[HTMLText new] appendNode:doctype]);
|
||||
}
|
||||
|
||||
- (void)testValidParentForText
|
||||
{
|
||||
HTMLText *text = [HTMLText new];
|
||||
|
||||
XCTAssertThrows([[HTMLDocument new] appendNode:text]);
|
||||
XCTAssertThrows([[HTMLDocumentType new] appendNode:text]);
|
||||
XCTAssertThrows([[HTMLComment new] appendNode:text]);
|
||||
XCTAssertThrows([[HTMLText new] appendNode:text]);
|
||||
|
||||
XCTAssertNoThrow([[HTMLDocumentFragment new] appendNode:text]);
|
||||
XCTAssertNoThrow([[HTMLElement new] appendNode:text]);
|
||||
XCTAssertNoThrow([[HTMLTemplate new] appendNode:text]);
|
||||
}
|
||||
|
||||
- (void)testValidDocumentFragmentInsertionIntoDocument
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
HTMLDocumentFragment *fragment = [[HTMLDocumentFragment alloc] initWithDocument:document];
|
||||
|
||||
void (^ reset)() = ^ {
|
||||
[fragment removeAllChildNodes];
|
||||
[document removeAllChildNodes];
|
||||
};
|
||||
|
||||
/**
|
||||
* Fragment has a Text node child
|
||||
*/
|
||||
[fragment appendNode:[HTMLText new]];
|
||||
XCTAssertThrows([document appendNode:fragment]);
|
||||
|
||||
/**
|
||||
* Fragment has more than one Element child
|
||||
*/
|
||||
reset();
|
||||
[fragment appendNode:[HTMLElement new]];
|
||||
[fragment appendNode:[HTMLElement new]];
|
||||
XCTAssertThrows([document appendNode:fragment]);
|
||||
|
||||
|
||||
/**
|
||||
* Fragment has one node child
|
||||
* Document has an Element child
|
||||
*/
|
||||
reset();
|
||||
[fragment appendNode:[HTMLElement new]];
|
||||
[document appendNode:[HTMLElement new]];
|
||||
XCTAssertThrows([document appendNode:fragment]);
|
||||
|
||||
/**
|
||||
* Fragment has one node child
|
||||
* "before child" is a Doctype
|
||||
*/
|
||||
reset();
|
||||
HTMLDocumentType *doctype = [HTMLDocumentType new];
|
||||
[fragment appendNode:[HTMLElement new]];
|
||||
[document appendNode:doctype];
|
||||
XCTAssertThrows([document insertNode:fragment beforeChildNode:doctype]);
|
||||
|
||||
/**
|
||||
* Fragment has one node child
|
||||
* "before child" is following a Doctype
|
||||
*/
|
||||
reset();
|
||||
HTMLComment *doctypePreviousSibling = [HTMLComment new];
|
||||
[fragment appendNode:[HTMLElement new]];
|
||||
[document appendNode:doctypePreviousSibling];
|
||||
[document appendNode:doctype];
|
||||
XCTAssertThrows([document insertNode:fragment beforeChildNode:doctypePreviousSibling]);
|
||||
}
|
||||
|
||||
- (void)testValidElementInsertionIntoDocument
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
HTMLElement *element = [HTMLElement new];
|
||||
|
||||
void (^ reset)() = ^ {
|
||||
[element removeAllChildNodes];
|
||||
[document removeAllChildNodes];
|
||||
};
|
||||
|
||||
/**
|
||||
* Document has an Element child
|
||||
*/
|
||||
[document appendNode:[HTMLElement new]];
|
||||
XCTAssertThrows([document appendNode:element]);
|
||||
|
||||
/**
|
||||
* "before child" is a Doctype
|
||||
*/
|
||||
reset();
|
||||
HTMLDocumentType *doctype = [HTMLDocumentType new];
|
||||
[document appendNode:doctype];
|
||||
XCTAssertThrows([document insertNode:element beforeChildNode:doctype]);
|
||||
|
||||
/**
|
||||
* Doctype is following the "before child"
|
||||
*/
|
||||
reset();
|
||||
HTMLComment *doctypePreviousSibling = [HTMLComment new];
|
||||
[document appendNode:doctypePreviousSibling];
|
||||
[document appendNode:doctype];
|
||||
XCTAssertThrows([document insertNode:element beforeChildNode:doctypePreviousSibling]);
|
||||
}
|
||||
|
||||
- (void)testValidDoctypeInsertionIntoDocument
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
HTMLDocumentType *doctype = [HTMLDocumentType new];
|
||||
|
||||
void (^ reset)() = ^ {
|
||||
[document removeAllChildNodes];
|
||||
};
|
||||
|
||||
/**
|
||||
* Document has a Doctype child
|
||||
*/
|
||||
[document appendNode:[HTMLDocumentType new]];
|
||||
XCTAssertThrows([document appendNode:doctype]);
|
||||
|
||||
/**
|
||||
* An Element is preceding the "before child"
|
||||
*/
|
||||
reset();
|
||||
HTMLComment *secondChild = [HTMLComment new];
|
||||
[document appendNode:[HTMLElement new]];
|
||||
[document appendNode:secondChild];
|
||||
XCTAssertThrows([document insertNode:doctype beforeChildNode:secondChild]);
|
||||
|
||||
/**
|
||||
* Document has an Element child
|
||||
*/
|
||||
reset();
|
||||
[document appendNode:[HTMLElement new]];
|
||||
XCTAssertThrows([document appendNode:doctype]);
|
||||
}
|
||||
|
||||
- (void)testValidDocumentFragmentReplacementIntoDocument
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
HTMLComment *child = [HTMLComment new];
|
||||
HTMLDocumentFragment *replacement = [[HTMLDocumentFragment alloc] initWithDocument:document];
|
||||
|
||||
void (^ reset)() = ^ {
|
||||
[replacement removeAllChildNodes];
|
||||
[document removeAllChildNodes];
|
||||
[document appendNode:child];
|
||||
};
|
||||
|
||||
/**
|
||||
* Replacement Fragment has a Text node child
|
||||
*/
|
||||
[replacement appendNode:[HTMLText new]];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
|
||||
/**
|
||||
* Replacement Fragment has more than one Element child
|
||||
*/
|
||||
reset();
|
||||
[replacement appendNode:[HTMLElement new]];
|
||||
[replacement appendNode:[HTMLElement new]];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
|
||||
/**
|
||||
* Replacement Fragment has one Element child
|
||||
* Document has an Element child that is not the Replacement
|
||||
*/
|
||||
reset();
|
||||
[replacement appendNode:[HTMLElement new]];
|
||||
[document appendNode:[HTMLElement new]];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
|
||||
/**
|
||||
* Replacement Fragment has one Element child
|
||||
* Doctype is following the child node
|
||||
*/
|
||||
reset();
|
||||
HTMLDocumentType *doctype = [HTMLDocumentType new];
|
||||
[replacement appendNode:[HTMLElement new]];
|
||||
[document appendNode:doctype];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
}
|
||||
|
||||
- (void)testValidElementReplacementIntoDocument
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
HTMLComment *child = [HTMLComment new];
|
||||
HTMLElement *replacement = [HTMLElement new];
|
||||
|
||||
void (^ reset)() = ^ {
|
||||
[replacement removeAllChildNodes];
|
||||
[document removeAllChildNodes];
|
||||
[document appendNode:child];
|
||||
};
|
||||
|
||||
/**
|
||||
* Docment has an Element child that is not replacement
|
||||
*/
|
||||
[document appendNode:[HTMLElement new]];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
|
||||
/**
|
||||
* Doctype is following the child node
|
||||
*/
|
||||
reset();
|
||||
HTMLDocumentType *doctype = [HTMLDocumentType new];
|
||||
[document appendNode:doctype];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
}
|
||||
|
||||
- (void)testValidDoctypeReplacementIntoDocument
|
||||
{
|
||||
HTMLDocument *document = [HTMLDocument new];
|
||||
HTMLComment *child = [HTMLComment new];
|
||||
HTMLDocumentType *replacement = [HTMLDocumentType new];
|
||||
|
||||
void (^ reset)() = ^ {
|
||||
[replacement removeAllChildNodes];
|
||||
[document removeAllChildNodes];
|
||||
[document appendNode:child];
|
||||
};
|
||||
|
||||
/**
|
||||
* Docment has an Doctype child that is not replacement
|
||||
*/
|
||||
[document appendNode:[HTMLDocumentType new]];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
|
||||
/**
|
||||
* An Element is preceding the child node
|
||||
*/
|
||||
reset();
|
||||
[document insertNode:[HTMLElement new] beforeChildNode:child];
|
||||
XCTAssertThrows([document replaceChildNode:child withNode:replacement]);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -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
|
||||
@@ -0,0 +1,485 @@
|
||||
//
|
||||
// HTMLKitNodesTests.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 20/04/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "HTMLDOM.h"
|
||||
|
||||
@interface HTMLKitNodesTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation HTMLKitNodesTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
{
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testInitNode
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
XCTAssertNotNil(node);
|
||||
XCTAssertEqualObjects(node.name, @"name");
|
||||
XCTAssertEqual(node.nodeType, HTMLNodeElement);
|
||||
XCTAssertNotNil(node.childNodes);
|
||||
XCTAssertEqual(node.childNodes.count, 0);
|
||||
|
||||
XCTAssertNil(node.ownerDocument);
|
||||
XCTAssertNil(node.parentNode);
|
||||
XCTAssertNil(node.parentElement);
|
||||
XCTAssertNil(node.firstChild);
|
||||
XCTAssertNil(node.lastChild);
|
||||
XCTAssertNil(node.previousSibling);
|
||||
XCTAssertNil(node.lastChild);
|
||||
}
|
||||
|
||||
- (void)testAppendNode
|
||||
{
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
HTMLComment *comment = [HTMLComment new];
|
||||
[element appendNode:comment];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 1);
|
||||
XCTAssertEqual(element.firstChild, comment);
|
||||
|
||||
HTMLElement *firstElement = [HTMLElement new];
|
||||
HTMLElement *secondElement = [HTMLElement new];
|
||||
NSArray *nodes = @[firstElement, secondElement];
|
||||
|
||||
[element appendNodes:nodes];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 3);
|
||||
XCTAssertEqual(element.firstChild, comment);
|
||||
XCTAssertEqual(element.lastChild, secondElement);
|
||||
}
|
||||
|
||||
- (void)testPrependNode
|
||||
{
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
HTMLText *text = [HTMLText new];
|
||||
[element appendNode:text];
|
||||
|
||||
HTMLComment *comment = [HTMLComment new];
|
||||
[element prependNode:comment];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 2);
|
||||
XCTAssertEqual(element.firstChild, comment);
|
||||
|
||||
HTMLElement *firstElement = [HTMLElement new];
|
||||
HTMLElement *secondElement = [HTMLElement new];
|
||||
NSArray *nodes = @[firstElement, secondElement];
|
||||
|
||||
[element prependNodes:nodes];
|
||||
|
||||
XCTAssertEqual(element.childNodesCount, 4);
|
||||
XCTAssertEqual(element.firstChild, firstElement);
|
||||
XCTAssertEqual(element.lastChild, text);
|
||||
}
|
||||
|
||||
- (void)testAppendDocumentFragment
|
||||
{
|
||||
HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div"];
|
||||
HTMLComment *comment = [HTMLComment new];
|
||||
[element appendNode:comment];
|
||||
|
||||
HTMLDocumentFragment *fragment = [HTMLDocumentFragment new];
|
||||
HTMLElement *firstChild = [HTMLElement new];
|
||||
HTMLElement *secondChild = [HTMLElement new];
|
||||
[fragment appendNode:firstChild];
|
||||
[fragment appendNode:secondChild];
|
||||
|
||||
[element appendNode:fragment];
|
||||
XCTAssertEqual(element.childNodesCount, 3);
|
||||
XCTAssertEqual(fragment.childNodesCount, 0);
|
||||
|
||||
XCTAssertEqualObjects(firstChild.parentNode, element);
|
||||
XCTAssertEqualObjects(secondChild.parentNode, element);
|
||||
XCTAssertEqualObjects(element.firstChild, comment);
|
||||
XCTAssertEqualObjects(element.firstChild.nextSibling, firstChild);
|
||||
XCTAssertEqualObjects(element.lastChild.previousSibling, firstChild);
|
||||
XCTAssertEqualObjects(element.lastChild, secondChild);
|
||||
}
|
||||
|
||||
- (void)testParentNode
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
XCTAssertNil(firstChild.parentNode);
|
||||
|
||||
[node appendNode:firstChild];
|
||||
XCTAssertTrue(node.hasChildNodes);
|
||||
XCTAssertEqual(node.childNodesCount, 1);
|
||||
|
||||
XCTAssertNotNil(firstChild.parentNode);
|
||||
XCTAssertEqualObjects(firstChild.parentNode, node);
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
|
||||
[node appendNodes:@[secondChild, thirdChild]];
|
||||
XCTAssertTrue(node.hasChildNodes);
|
||||
XCTAssertEqual(node.childNodesCount, 3);
|
||||
|
||||
XCTAssertNotNil(secondChild.parentNode);
|
||||
XCTAssertEqualObjects(secondChild.parentNode, node);
|
||||
|
||||
XCTAssertNotNil(thirdChild.parentNode);
|
||||
XCTAssertEqualObjects(thirdChild.parentNode, node);
|
||||
}
|
||||
|
||||
- (void)testChildNodesCount
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
XCTAssertFalse(node.hasChildNodes);
|
||||
XCTAssertEqual(node.childNodesCount, 0);
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
XCTAssertTrue(node.hasChildNodes);
|
||||
XCTAssertEqual(node.childNodesCount, 1);
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
XCTAssertTrue(node.hasChildNodes);
|
||||
XCTAssertEqual(node.childNodesCount, 2);
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
XCTAssertTrue(node.hasChildNodes);
|
||||
XCTAssertEqual(node.childNodesCount, 3);
|
||||
}
|
||||
|
||||
- (void)testFirstAndLastChildNodes
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
XCTAssertEqualObjects(node.firstChild, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChild, firstChild);
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
XCTAssertEqualObjects(node.firstChild, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChild, secondChild);
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
XCTAssertEqualObjects(node.firstChild, firstChild);
|
||||
XCTAssertEqualObjects(node.lastChild, thirdChild);
|
||||
}
|
||||
|
||||
- (void)testNextAndPreviousSiblingNodes
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
XCTAssertNil(firstChild.previousSibling);
|
||||
XCTAssertEqualObjects(firstChild.nextSibling, secondChild);
|
||||
|
||||
XCTAssertEqualObjects(secondChild.previousSibling, firstChild);
|
||||
XCTAssertEqualObjects(secondChild.nextSibling, thirdChild);
|
||||
|
||||
XCTAssertEqualObjects(thirdChild.previousSibling, secondChild);
|
||||
XCTAssertNil(thirdChild.nextSibling);
|
||||
}
|
||||
|
||||
- (void)testHasChildNodeOfType
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
XCTAssertFalse([node hasChildNodeOfType:HTMLNodeElement]);
|
||||
XCTAssertFalse([node hasChildNodeOfType:HTMLNodeText]);
|
||||
XCTAssertFalse([node hasChildNodeOfType:HTMLNodeComment]);
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
XCTAssertTrue([node hasChildNodeOfType:HTMLNodeElement]);
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeText];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
XCTAssertTrue([node hasChildNodeOfType:HTMLNodeText]);
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeComment];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
XCTAssertTrue([node hasChildNodeOfType:HTMLNodeComment]);
|
||||
}
|
||||
|
||||
- (void)testChildNodeAtIndex
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
XCTAssertEqualObjects([node childNodeAtIndex:0], firstChild);
|
||||
XCTAssertEqualObjects([node childNodeAtIndex:1], secondChild);
|
||||
XCTAssertEqualObjects([node childNodeAtIndex:2], thirdChild);
|
||||
}
|
||||
|
||||
- (void)testIndexOfChildNode
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], 0);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], 1);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 2);
|
||||
}
|
||||
|
||||
- (void)testIndertNodeBeforeChild
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node insertNode:secondChild beforeChildNode:firstChild];
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], 1);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], 0);
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node insertNode:thirdChild beforeChildNode:firstChild];
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], 2);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], 0);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 1);
|
||||
}
|
||||
|
||||
- (void)testReplaceChildNode
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node replaceChildNode:firstChild withNode:thirdChild];
|
||||
|
||||
XCTAssertNil(firstChild.parentNode);
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], 1);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 0);
|
||||
}
|
||||
|
||||
- (void)testReplaceAllChildNodes
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node replaceAllChildNodesWithNode:thirdChild];
|
||||
|
||||
XCTAssertNil(firstChild.parentNode);
|
||||
XCTAssertNil(secondChild.parentNode);
|
||||
XCTAssertEqualObjects(thirdChild.parentNode, node);
|
||||
|
||||
XCTAssertEqual(node.childNodesCount, 1);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 0);
|
||||
}
|
||||
|
||||
- (void)testRemoveFromParentNode
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
[firstChild removeFromParentNode];
|
||||
|
||||
XCTAssertNil(firstChild.parentNode);
|
||||
XCTAssertEqual(node.childNodesCount, 0);
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], NSNotFound);
|
||||
}
|
||||
|
||||
- (void)testRemoveChildNode
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
[node removeChildNode:secondChild];
|
||||
XCTAssertEqual(node.childNodesCount, 2);
|
||||
|
||||
XCTAssertEqualObjects(firstChild.parentNode, node);
|
||||
XCTAssertNil(secondChild.parentNode);
|
||||
XCTAssertEqualObjects(thirdChild.parentNode, node);
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], 0);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 1);
|
||||
|
||||
[node removeChildNode:firstChild];
|
||||
XCTAssertEqual(node.childNodesCount, 1);
|
||||
|
||||
XCTAssertNil(firstChild.parentNode);
|
||||
XCTAssertNil(secondChild.parentNode);
|
||||
XCTAssertEqualObjects(thirdChild.parentNode, node);
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 0);
|
||||
}
|
||||
|
||||
- (void)testRemoveChildNodeAtIndex
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
[node removeChildNodeAtIndex:1];
|
||||
XCTAssertEqual(node.childNodesCount, 2);
|
||||
|
||||
XCTAssertEqualObjects(firstChild.parentNode, node);
|
||||
XCTAssertNil(secondChild.parentNode);
|
||||
XCTAssertEqualObjects(thirdChild.parentNode, node);
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], 0);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 1);
|
||||
|
||||
[node removeChildNodeAtIndex:0];
|
||||
XCTAssertEqual(node.childNodesCount, 1);
|
||||
|
||||
XCTAssertNil(firstChild.parentNode);
|
||||
XCTAssertNil(secondChild.parentNode);
|
||||
XCTAssertEqualObjects(thirdChild.parentNode, node);
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], 0);
|
||||
}
|
||||
|
||||
- (void)testRemoveAllChildNodes
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
[node removeAllChildNodes];
|
||||
XCTAssertEqual(node.childNodesCount, 0);
|
||||
|
||||
XCTAssertNil(firstChild.parentNode);
|
||||
XCTAssertNil(secondChild.parentNode);
|
||||
XCTAssertNil(thirdChild.parentNode);
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], NSNotFound);
|
||||
}
|
||||
|
||||
- (void)testReparentChildNodes
|
||||
{
|
||||
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
|
||||
|
||||
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
|
||||
[node appendNode:firstChild];
|
||||
|
||||
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
|
||||
[node appendNode:secondChild];
|
||||
|
||||
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
|
||||
[node appendNode:thirdChild];
|
||||
|
||||
HTMLNode *newParent = [[HTMLNode alloc] initWithName:@"new-parent" type:HTMLNodeElement];
|
||||
|
||||
[node reparentChildNodesIntoNode:newParent];
|
||||
XCTAssertEqual(node.childNodesCount, 0);
|
||||
|
||||
XCTAssertEqual([node indexOfChildNode:firstChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:secondChild], NSNotFound);
|
||||
XCTAssertEqual([node indexOfChildNode:thirdChild], NSNotFound);
|
||||
|
||||
XCTAssertEqualObjects(firstChild.parentNode, newParent);
|
||||
XCTAssertEqualObjects(secondChild.parentNode, newParent);
|
||||
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