Add NSString category for HTML related methods
Also remove macros scattered throughout the code and use category consistently
This commit is contained in:
@@ -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 = "<group>"; };
|
||||
6234584C1A9D2FA4009BD491 /* HTMLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLNode.h; sourceTree = "<group>"; };
|
||||
6234584D1A9D2FA4009BD491 /* HTMLNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLNode.m; sourceTree = "<group>"; };
|
||||
6235CE991AA509430026937B /* NSString+HTMLKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+HTMLKit.h"; sourceTree = "<group>"; };
|
||||
6235CE9A1AA509430026937B /* NSString+HTMLKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+HTMLKit.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>"; };
|
||||
@@ -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 */,
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+17
-16
@@ -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 <html>", 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 <head>", 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 <head>", 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 <head><noscript>", token.asStartTagToken.tagName];
|
||||
return;
|
||||
}
|
||||
@@ -698,7 +699,7 @@
|
||||
[self insertElementForToken:token.asTagToken];
|
||||
[self switchInsertionMode:HTMLInsertionModeInFrameset];
|
||||
return;
|
||||
} else if (matches(token.asStartTagToken.tagName, @"base", @"basefont", @"bgsound", @"link", @"meta", @"noframes", @"script", @"style", @"template", @"title")) {
|
||||
} else if ([token.asStartTagToken.tagName isEqualToAny:@"base", @"basefont", @"bgsound", @"link", @"meta", @"noframes", @"script", @"style", @"template", @"title", nil]) {
|
||||
[self emitParseError:@"Unexpected Start Tag Token (%@) after <head>", token.asStartTagToken.tagName];
|
||||
[_stackOfOpenElements addObject:_headElementPointer];
|
||||
[self HTMLInsertionModeInHead:token];
|
||||
@@ -713,7 +714,7 @@
|
||||
if ([token.asEndTagToken.tagName isEqualToString:@"template"]) {
|
||||
#warning Implement HTML Template
|
||||
[self HTMLInsertionModeInHead:token];
|
||||
} 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 (%@) after <head>", token.asEndTagToken.tagName];
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// NSString+HTMLKit.h
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 02/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSString (HTMLKit)
|
||||
|
||||
- (BOOL)isEqualToAny:(NSString *)first, ... NS_REQUIRES_NIL_TERMINATION;
|
||||
- (BOOL)isHTMLWhitespaceString;
|
||||
- (NSUInteger)leadingWhitespaceLength;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// NSString+HTMLKit.m
|
||||
// HTMLKit
|
||||
//
|
||||
// Created by Iska on 02/03/15.
|
||||
// Copyright (c) 2015 BrainCookie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSString+HTMLKit.h"
|
||||
|
||||
NS_INLINE BOOL isHtmlWhitespaceChar(char c)
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r';
|
||||
}
|
||||
|
||||
@implementation NSString (HTMLKit)
|
||||
|
||||
- (BOOL)isEqualToAny:(NSString *)first, ... NS_REQUIRES_NIL_TERMINATION
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, first);
|
||||
for (NSString *next = first; next != nil; next = va_arg(list, NSString *)) {
|
||||
if ([self isEqualToString:next]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
va_end(list);
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isHTMLWhitespaceString
|
||||
{
|
||||
NSCharacterSet *set = [[NSCharacterSet characterSetWithCharactersInString:@" \t\n\f\r"] invertedSet];
|
||||
return [self rangeOfCharacterFromSet:set].location == NSNotFound;
|
||||
}
|
||||
|
||||
- (NSUInteger)leadingWhitespaceLength
|
||||
{
|
||||
const char *str = self.UTF8String;
|
||||
size_t idx = 0;
|
||||
while (isHtmlWhitespaceChar(*str)) { str++; idx++; }
|
||||
return idx;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user