From 40400864d8dae48c5933894e895c5e33a00b467b Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 5 Jun 2015 18:06:23 +0200 Subject: [PATCH] Add block-based API for Node Filter - HTMLNodeFilterBlock is a block-based class implementation conforming to HTMLNodeFilter - HTMLNode & NodeIterator get block-based initializers --- HTMLKit.xcodeproj/project.pbxproj | 6 ++++ HTMLKit/HTMLNode.h | 3 ++ HTMLKit/HTMLNode.m | 6 ++++ HTMLKit/HTMLNodeFilter.h | 6 ++++ HTMLKit/HTMLNodeFilter.m | 42 +++++++++++++++++++++++++ HTMLKit/HTMLNodeIterator.h | 4 +++ HTMLKit/HTMLNodeIterator.m | 11 +++++++ HTMLKitTests/HTMLKitNodeIteratorTests.m | 27 +++++----------- 8 files changed, 86 insertions(+), 19 deletions(-) create mode 100644 HTMLKit/HTMLNodeFilter.m diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 4f4907f..350eb6c 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -66,6 +66,8 @@ 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 */; }; + 624717B81B21FE5400B38302 /* HTMLNodeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */; }; + 624717B91B21FE5400B38302 /* HTMLNodeFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 624717B71B21FE5400B38302 /* HTMLNodeFilter.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 */; }; @@ -211,6 +213,7 @@ 624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerStates.h; sourceTree = ""; }; 624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLToken.h; sourceTree = ""; }; 624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLToken.m; sourceTree = ""; }; + 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeFilter.m; sourceTree = ""; }; 6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeIterator.h; sourceTree = ""; }; 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNodeIterator.m; sourceTree = ""; }; 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNodeFilter.h; sourceTree = ""; }; @@ -338,6 +341,7 @@ 6247A9411B152F4F00CCF25C /* HTMLNodeIterator.h */, 6247A9421B152F4F00CCF25C /* HTMLNodeIterator.m */, 6247A9461B152F8C00CCF25C /* HTMLNodeFilter.h */, + 624717B71B21FE5400B38302 /* HTMLNodeFilter.m */, 6238C9831AB8D6330006512E /* HTMLKitDOMExceptions.h */, 6238C9841AB8D6330006512E /* HTMLKitDOMExceptions.m */, 628B7CE61A080E1000602C87 /* HTMLNamespaces.h */, @@ -755,6 +759,7 @@ 625A150A19C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */, 623857931A9E772B003A45D9 /* HTMLDocument.m in Sources */, 623406E81ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */, + 624717B91B21FE5400B38302 /* HTMLNodeFilter.m in Sources */, 624493A819CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */, 625A14BE19C7829400AD0C32 /* HTMLKit.m in Sources */, 623857981A9E8606003A45D9 /* HTMLDocumentType.m in Sources */, @@ -807,6 +812,7 @@ 625A150919C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */, 623857921A9E772B003A45D9 /* HTMLDocument.m in Sources */, 623406E71ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */, + 624717B81B21FE5400B38302 /* HTMLNodeFilter.m in Sources */, 624493A719CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */, 625A150219C783DE00AD0C32 /* HTMLKit.m in Sources */, 623857971A9E8606003A45D9 /* HTMLDocumentType.m in Sources */, diff --git a/HTMLKit/HTMLNode.h b/HTMLKit/HTMLNode.h index c681825..ac4a20c 100644 --- a/HTMLKit/HTMLNode.h +++ b/HTMLKit/HTMLNode.h @@ -118,6 +118,9 @@ typedef NS_ENUM(unsigned short, HTMLDocumentPosition) - (HTMLNodeIterator *)nodeIterator; - (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions filter:(id)filter; +- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions + filterBlock:(BOOL (^)(HTMLNode *node))filter; + - (NSString *)treeDescription; @end diff --git a/HTMLKit/HTMLNode.m b/HTMLKit/HTMLNode.m index c4d166f..6f4a221 100644 --- a/HTMLKit/HTMLNode.m +++ b/HTMLKit/HTMLNode.m @@ -380,6 +380,12 @@ return [[HTMLNodeIterator alloc] initWithNode:self showOptions:showOptions filter:filter]; } +- (HTMLNodeIterator *)nodeIteratorWithShowOptions:(HTMLNodeFilterShowOptions)showOptions + filterBlock:(BOOL (^)(HTMLNode *node))filter +{ + return [HTMLNodeIterator iteratorWithNode:self showOptions:showOptions filter:filter]; +} + #ifndef HTMLKIT_NO_DOM_CHECKS #pragma mark - Validity Checks diff --git a/HTMLKit/HTMLNodeFilter.h b/HTMLKit/HTMLNodeFilter.h index 40785a3..84c4c57 100644 --- a/HTMLKit/HTMLNodeFilter.h +++ b/HTMLKit/HTMLNodeFilter.h @@ -26,3 +26,9 @@ typedef NS_ENUM(unsigned long, HTMLNodeFilterShowOptions) - (BOOL)acceptNode:(HTMLNode *)node; @end + +@interface HTMLNodeFilterBlock : NSObject + ++ (instancetype)filterWithBlock:(BOOL (^)(HTMLNode *node))block; + +@end \ No newline at end of file diff --git a/HTMLKit/HTMLNodeFilter.m b/HTMLKit/HTMLNodeFilter.m new file mode 100644 index 0000000..914ee72 --- /dev/null +++ b/HTMLKit/HTMLNodeFilter.m @@ -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:(BOOL (^)(HTMLNode *))block +{ + return [[self alloc] initWithBlock:block]; +} + +- (instancetype)initWithBlock:(BOOL (^)(HTMLNode *))block +{ + self = [super init]; + if (self) { + _block = [block copy]; + } + return self; +} + +- (BOOL)acceptNode:(HTMLNode *)node +{ + if (!_block) { + return NO; + } + + return _block(node); +} + +@end diff --git a/HTMLKit/HTMLNodeIterator.h b/HTMLKit/HTMLNodeIterator.h index ed8bd2b..803f55e 100644 --- a/HTMLKit/HTMLNodeIterator.h +++ b/HTMLKit/HTMLNodeIterator.h @@ -19,6 +19,10 @@ @property (nonatomic, assign, readonly) HTMLNodeFilterShowOptions whatToShow; @property (nonatomic, strong, readonly) id filter; ++ (instancetype)iteratorWithNode:(HTMLNode *)node + showOptions:(HTMLNodeFilterShowOptions)showOptions + filter:(BOOL (^)(HTMLNode *node))filter; + - (instancetype)initWithNode:(HTMLNode *)node; - (instancetype)initWithNode:(HTMLNode *)node filter:(id)filter; diff --git a/HTMLKit/HTMLNodeIterator.m b/HTMLKit/HTMLNodeIterator.m index a23de3d..1f72bed 100644 --- a/HTMLKit/HTMLNodeIterator.m +++ b/HTMLKit/HTMLNodeIterator.m @@ -10,6 +10,8 @@ #import "HTMLDocument.h" #import "HTMLNode.h" +#import + typedef NS_ENUM(short, TraverseDirection) { TraverseDirectionNext, @@ -31,6 +33,15 @@ typedef NS_ENUM(short, TraverseDirection) #pragma mark - Lifecycle ++ (instancetype)iteratorWithNode:(HTMLNode *)node + showOptions:(HTMLNodeFilterShowOptions)showOptions + filter:(BOOL (^)(HTMLNode *))filter +{ + return [[self alloc] initWithNode:node + showOptions:showOptions + filter:[HTMLNodeFilterBlock filterWithBlock:filter]]; +} + - (instancetype)initWithNode:(HTMLNode *)node { return [self initWithNode:node filter:nil]; diff --git a/HTMLKitTests/HTMLKitNodeIteratorTests.m b/HTMLKitTests/HTMLKitNodeIteratorTests.m index a9b05f2..a6411f3 100644 --- a/HTMLKitTests/HTMLKitNodeIteratorTests.m +++ b/HTMLKitTests/HTMLKitNodeIteratorTests.m @@ -9,23 +9,6 @@ #import #import "HTMLDOM.h" -@interface CommentNodeFilter : NSObject -@end - -@implementation CommentNodeFilter - -- (BOOL)acceptNode:(HTMLNode *)node -{ - if (node.nodeType == HTMLNodeComment) { - if ([[(HTMLComment *)node data] rangeOfString:@"second"].location != NSNotFound) { - return YES; - } - } - return NO; -} - -@end - @interface HTMLKitNodeIteratorTests : XCTestCase @end @@ -327,8 +310,14 @@ { HTMLDocument *document = self.mixedTree; - HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowAll - filter:[CommentNodeFilter new]]; + HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowAll filterBlock:^BOOL(HTMLNode *node) { + if (node.nodeType == HTMLNodeComment) { + if ([[(HTMLComment *)node data] rangeOfString:@"second"].location != NSNotFound) { + return YES; + } + } + return NO; + }]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"#comment"];