diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index 9a3a8b6..13906ec 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -10,6 +10,9 @@ 6234584E1A9D2FA4009BD491 /* HTMLNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 6234584C1A9D2FA4009BD491 /* HTMLNode.h */; }; 6234584F1A9D2FA4009BD491 /* HTMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 6234584D1A9D2FA4009BD491 /* HTMLNode.m */; }; 623458501A9D2FA4009BD491 /* HTMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 6234584D1A9D2FA4009BD491 /* HTMLNode.m */; }; + 6235CE9B1AA509430026937B /* NSString+HTMLKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6235CE991AA509430026937B /* NSString+HTMLKit.h */; }; + 6235CE9C1AA509430026937B /* NSString+HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6235CE9A1AA509430026937B /* NSString+HTMLKit.m */; }; + 6235CE9D1AA509430026937B /* NSString+HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6235CE9A1AA509430026937B /* NSString+HTMLKit.m */; }; 62362A3C1A9FA70400301989 /* HTMLText.h in Headers */ = {isa = PBXBuildFile; fileRef = 62362A3A1A9FA70400301989 /* HTMLText.h */; }; 62362A3D1A9FA70400301989 /* HTMLText.m in Sources */ = {isa = PBXBuildFile; fileRef = 62362A3B1A9FA70400301989 /* HTMLText.m */; }; 62362A3E1A9FA70400301989 /* HTMLText.m in Sources */ = {isa = PBXBuildFile; fileRef = 62362A3B1A9FA70400301989 /* HTMLText.m */; }; @@ -116,6 +119,8 @@ 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLElementTypes.h; sourceTree = ""; }; 6234584C1A9D2FA4009BD491 /* HTMLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNode.h; sourceTree = ""; }; 6234584D1A9D2FA4009BD491 /* HTMLNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNode.m; sourceTree = ""; }; + 6235CE991AA509430026937B /* NSString+HTMLKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+HTMLKit.h"; sourceTree = ""; }; + 6235CE9A1AA509430026937B /* NSString+HTMLKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+HTMLKit.m"; sourceTree = ""; }; 62362A3A1A9FA70400301989 /* HTMLText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLText.h; sourceTree = ""; }; 62362A3B1A9FA70400301989 /* HTMLText.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLText.m; sourceTree = ""; }; 62362A3F1A9FDE8A00301989 /* HTMLNodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLNodes.h; sourceTree = ""; }; @@ -293,6 +298,8 @@ 628B7CE61A080E1000602C87 /* HTMLNamespaces.h */, 6223211D1A969B9300BACED5 /* HTMLElementTypes.h */, 6279F87119E17DC700F12EE5 /* HTMLParserInsertionModes.h */, + 6235CE991AA509430026937B /* NSString+HTMLKit.h */, + 6235CE9A1AA509430026937B /* NSString+HTMLKit.m */, 623719441AA1472B002E03C8 /* Nodes */, 625A14B619C7829400AD0C32 /* Supporting Files */, ); @@ -370,6 +377,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 6235CE9B1AA509430026937B /* NSString+HTMLKit.h in Headers */, 62F873EB19E088C90062683C /* HTMLParser.h in Headers */, 624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */, 62AE594419F992F30043F069 /* HTMLCommentToken.h in Headers */, @@ -538,6 +546,7 @@ buildActionMask = 2147483647; files = ( 62362A3E1A9FA70400301989 /* HTMLText.m in Sources */, + 6235CE9D1AA509430026937B /* NSString+HTMLKit.m in Sources */, 6238579D1A9E8934003A45D9 /* HTMLComment.m in Sources */, 624493AE19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */, 62AE594119F9907C0043F069 /* HTMLTagToken.m in Sources */, @@ -572,6 +581,7 @@ buildActionMask = 2147483647; files = ( 62362A3D1A9FA70400301989 /* HTMLText.m in Sources */, + 6235CE9C1AA509430026937B /* NSString+HTMLKit.m in Sources */, 6238579C1A9E8934003A45D9 /* HTMLComment.m in Sources */, 624493AD19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */, 62AE594019F9907C0043F069 /* HTMLTagToken.m in Sources */, diff --git a/HTMLKit/HTMLCharacterToken.m b/HTMLKit/HTMLCharacterToken.m index 9255bd1..257fb2e 100644 --- a/HTMLKit/HTMLCharacterToken.m +++ b/HTMLKit/HTMLCharacterToken.m @@ -7,19 +7,7 @@ // #import "HTMLCharacterToken.h" - -NS_INLINE BOOL isHtmlWhitespace(char c) -{ - return c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r'; -} - -NS_INLINE size_t LeadingWhitespaceLength(NSString *string) -{ - const char *str = string.UTF8String; - size_t idx = 0; - while (isHtmlWhitespace(*str)) { str++; idx++; } - return idx; -} +#import "NSString+HTMLKit.h" @interface HTMLCharacterToken () { @@ -48,14 +36,12 @@ NS_INLINE size_t LeadingWhitespaceLength(NSString *string) - (BOOL)isWhitespaceToken { -#warning Cache Character Set - NSCharacterSet *set = [[NSCharacterSet characterSetWithCharactersInString:@" \t\n\f"] invertedSet]; - return [_characters rangeOfCharacterFromSet:set].location == NSNotFound; + return [_characters isHTMLWhitespaceString]; } - (HTMLCharacterToken *)tokenByRetainingLeadingWhitespace { - size_t index = LeadingWhitespaceLength(_characters); + NSUInteger index = _characters.leadingWhitespaceLength; if (index > 0) { NSString *leading = [_characters substringToIndex:index]; return [[HTMLCharacterToken alloc] initWithString:leading]; @@ -65,7 +51,7 @@ NS_INLINE size_t LeadingWhitespaceLength(NSString *string) - (HTMLCharacterToken *)tokenByTrimmingLeadingWhitespace { - size_t index = LeadingWhitespaceLength(_characters); + NSUInteger index = _characters.leadingWhitespaceLength; if (index < _characters.length) { NSString *remaining = [_characters substringFromIndex:index]; return [[HTMLCharacterToken alloc] initWithString:remaining]; diff --git a/HTMLKit/HTMLElementTypes.h b/HTMLKit/HTMLElementTypes.h index 3cc9c95..afb3b1e 100644 --- a/HTMLKit/HTMLElementTypes.h +++ b/HTMLKit/HTMLElementTypes.h @@ -8,12 +8,11 @@ #import "HTMLElement.h" #import "HTMLNamespaces.h" - -#define matches(x, ...) [[NSSet setWithObjects:__VA_ARGS__, nil] containsObject:x] +#import "NSString+HTMLKit.h" NS_INLINE BOOL IsNodeMathMLTextIntegrationPoint(HTMLElement *node) { - return (node.namespace == HTMLNamespaceMathML && matches(node.tagName, @"mi", @"mo", @"mn", @"ms", @"mtext")); + return (node.namespace == HTMLNamespaceMathML && [node.tagName isEqualToAny:@"mi", @"mo", @"mn", @"ms", @"mtext", nil]); } NS_INLINE BOOL IsNodeHTMLIntegrationPoint(HTMLElement *node) @@ -21,7 +20,7 @@ NS_INLINE BOOL IsNodeHTMLIntegrationPoint(HTMLElement *node) if (node.namespace == HTMLNamespaceMathML && [node.tagName isEqualToString:@"annotation-xml"]) { #warning Implement HTML Element Attributes } else if (node.namespace == HTMLNamespaceSVG) { - return matches(node.tagName, @"foreignObject", @"desc", @"title"); + return [node.tagName isEqualToAny:@"foreignObject", @"desc", @"title", nil]; } return NO; } diff --git a/HTMLKit/HTMLParser.m b/HTMLKit/HTMLParser.m index b7d0cd3..15bf02f 100644 --- a/HTMLKit/HTMLParser.m +++ b/HTMLKit/HTMLParser.m @@ -12,6 +12,7 @@ #import "HTMLParserInsertionModes.h" #import "HTMLNodes.h" #import "HTMLElementTypes.h" +#import "NSString+HTMLKit.h" @interface HTMLParser () { @@ -153,7 +154,7 @@ } if (last == NO) { - if (matches(node.tagName, @"td", @"th")) { + if ([node.tagName isEqualToAny:@"td", @"th", nil]) { [self switchInsertionMode:HTMLInsertionModeInCell]; return; } @@ -164,7 +165,7 @@ return; } - if (matches(node.tagName, @"tbody", @"thead", @"tfoot")) { + if ([node.tagName isEqualToAny:@"tbody", @"thead", @"tfoot", nil]) { [self switchInsertionMode:HTMLInsertionModeInTableBody]; return; } @@ -238,9 +239,9 @@ - (id)parseFragment { if (_contextElement != nil) { - if (matches(_contextElement.tagName, @"title", @"textarea")) { + if ([_contextElement.tagName isEqualToAny:@"title", @"textarea", nil]) { _tokenizer.state = HTMLTokenizerStateRCDATA; - } else if (matches(_contextElement.tagName, @"style", @"xmp", @"iframe", @"noembed", @"noframes")) { + } else if ([_contextElement.tagName isEqualToAny:@"style", @"xmp", @"iframe", @"noembed", @"noframes", nil]) { _tokenizer.state = HTMLTokenizerStateRAWTEXT; } else if ([_contextElement.tagName isEqualToString:@"script"]) { _tokenizer.state = HTMLTokenizerStateScriptData; @@ -251,7 +252,7 @@ } else if ([_contextElement.tagName isEqualToString:@"plaintext"]) { _tokenizer.state = HTMLTokenizerStatePLAINTEXT; } else { - _tokenizer = HTMLTokenizerStateData; + _tokenizer.state = HTMLTokenizerStateData; } } @@ -270,7 +271,7 @@ } if (IsNodeMathMLTextIntegrationPoint(node)) { if (token.type == HTMLTokenTypeStartTag) { - return !matches([(HTMLStartTagToken *)token tagName], @"mglyph", @"malignmark"); + return ![token.asStartTagToken.tagName isEqualToAny:@"mglyph", @"malignmark", nil]; } if (token.type == HTMLTokenTypeCharacter) { return YES; @@ -345,7 +346,7 @@ target = overrideTarget; } - if (_fosterParenting && matches(target.tagName, @"table", @"tbody", @"tfoot", @"thead", @"tr")) { + if (_fosterParenting && [target.tagName isEqualToAny:@"table", @"tbody", @"tfoot", @"thead", @"tr", nil]) { HTMLElement *lastTemplate = nil; HTMLElement *lastTable = nil; for (HTMLElement *element in _stackOfOpenElements.reverseObjectEnumerator) { @@ -490,7 +491,7 @@ } break; case HTMLTokenTypeEndTag: - if (!matches(token.asEndTagToken.tagName, @"head", @"body", @"html", @"br")) { + if (![token.asEndTagToken.tagName isEqualToAny:@"head", @"body", @"html", @"br", nil]) { [self emitParseError:@"Unexpected End Tag Token (%@) before ", token.asEndTagToken.tagName]; return; } @@ -530,7 +531,7 @@ } return; case HTMLTokenTypeEndTag: - if (!matches(token.asEndTagToken.tagName, @"head", @"body", @"html", @"br")) { + if (![token.asEndTagToken.tagName isEqualToAny:@"head", @"body", @"html", @"br", nil]) { [self emitParseError:@"Unexpected End Tag Token (%@) before ", token.asEndTagToken.tagName]; return; } @@ -570,7 +571,7 @@ if ([token.asStartTagToken.tagName isEqualToString:@"html"]) { [self HTMLInsertionModeInBody:token]; return; - } else if (matches(token.asStartTagToken.tagName, @"base", @"basefont", @"bgsound", @"link")) { + } else if ([token.asStartTagToken.tagName isEqualToAny:@"base", @"basefont", @"bgsound", @"link", nil]) { [self insertElementForToken:token.asStartTagToken]; [_stackOfOpenElements removeLastObject]; return; @@ -581,7 +582,7 @@ } else if ([token.asStartTagToken.tagName isEqualToString:@"title"]) { [self applyGenericParsingAlgorithmForToken:token.asStartTagToken withTokenizerState:HTMLTokenizerStateRCDATA]; return; - } else if (matches(token.asStartTagToken.tagName, @"noscript", @"noframes", @"style")) { + } else if ([token.asStartTagToken.tagName isEqualToAny:@"noscript", @"noframes", @"style", nil]) { [self applyGenericParsingAlgorithmForToken:token.asStartTagToken withTokenizerState:HTMLTokenizerStateRAWTEXT]; return; } else if ([token.asStartTagToken.tagName isEqualToString:@"script"]) { @@ -605,7 +606,7 @@ [_stackOfOpenElements removeLastObject]; [self switchInsertionMode:HTMLInsertionModeAfterHead]; return; - } else if (matches(token.asEndTagToken.tagName, @"body", @"html", @"br")) { + } else if ([token.asEndTagToken.tagName isEqualToAny:@"body", @"html", @"br", nil]) { break; } else { [self emitParseError:@"Unexpected End Tag Token (%@) in ", token.asEndTagToken.tagName]; @@ -631,10 +632,10 @@ if ([token.asStartTagToken.tagName isEqualToString:@"html"]) { [self HTMLInsertionModeInBody:token]; return; - } else if (matches(token.asStartTagToken.tagName, @"basefont", @"bgsound", @"link", @"meta", @"noframes", @"style")) { + } else if ([token.asStartTagToken.tagName isEqualToAny:@"basefont", @"bgsound", @"link", @"meta", @"noframes", @"style", nil]) { [self HTMLInsertionModeInHead:token]; return; - } else if (matches(token.asStartTagToken.tagName, @"head", @"noscript")) { + } else if ([token.asStartTagToken.tagName isEqualToAny:@"head", @"noscript", nil]) { [self emitParseError:@"Unexpected Start Tag Token (%@) in