diff --git a/HTMLKit/HTMLCharacterToken.h b/HTMLKit/HTMLCharacterToken.h
index 54841d8..f03dc58 100644
--- a/HTMLKit/HTMLCharacterToken.h
+++ b/HTMLKit/HTMLCharacterToken.h
@@ -17,4 +17,5 @@
- (void)appendString:(NSString *)string;
+- (BOOL)isWhitespaceToken;
@end
diff --git a/HTMLKit/HTMLCharacterToken.m b/HTMLKit/HTMLCharacterToken.m
index 47bceb9..33c4da3 100644
--- a/HTMLKit/HTMLCharacterToken.m
+++ b/HTMLKit/HTMLCharacterToken.m
@@ -33,6 +33,12 @@
[_characters appendString:string];
}
+- (BOOL)isWhitespaceToken
+{
+ NSCharacterSet *set = [[NSCharacterSet characterSetWithCharactersInString:@" \t\n\f"] invertedSet];
+ return [_characters rangeOfCharacterFromSet:set].location == NSNotFound;
+}
+
#pragma mark - NSObject
- (BOOL)isEqual:(id)other
diff --git a/HTMLKit/HTMLElement.h b/HTMLKit/HTMLElement.h
index 012b88d..0ddbafd 100644
--- a/HTMLKit/HTMLElement.h
+++ b/HTMLKit/HTMLElement.h
@@ -13,5 +13,6 @@
@property (nonatomic, strong, readonly) NSString *tagName;
@property (nonatomic, assign, readonly) HTMLNamespace namespace;
+@property (nonatomic, strong, readonly) id parentNode;
@end
diff --git a/HTMLKit/HTMLParser.m b/HTMLKit/HTMLParser.m
index e4ff477..c0479d4 100644
--- a/HTMLKit/HTMLParser.m
+++ b/HTMLKit/HTMLParser.m
@@ -9,6 +9,7 @@
#import "HTMLParser.h"
#import "HTMLTokenizer.h"
#import "HTMLTokens.h"
+#import "HTMLCharacterToken.h"
#import "HTMLParserInsertionModes.h"
#import "HTMLElement.h"
#import "HTMLElementTypes.h"
@@ -17,6 +18,8 @@
{
HTMLTokenizer *_tokenizer;
+ NSMutableArray *_errors;
+
NSMutableDictionary *_insertionModes;
HTMLInsertionMode _insertionMode;
HTMLInsertionMode _originalInsertionMode;
@@ -31,6 +34,7 @@
BOOL _scriptingFlag;
BOOL _fragmentParsingAlgorithm;
+ BOOL _fosterParting;
}
@end
@@ -42,6 +46,8 @@
{
self = [super init];
if (self) {
+ _errors = [NSMutableArray new];
+
_insertionModes = [NSMutableDictionary new];
_insertionMode = HTMLInsertionModeInitial;
[self setupStateMachine];
@@ -76,6 +82,17 @@
return [self currentNode];
}
+#pragma mark - Emits
+
+- (void)emitParseError:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2)
+{
+ va_list args;
+ va_start(args, format);
+ NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
+ [_errors addObject:message];
+ va_end(args);
+}
+
#pragma mark - State Machine
- (void)switchInsertionMode:(HTMLInsertionMode)mode
@@ -206,12 +223,13 @@
- (id)parse
{
for (HTMLToken *token in _tokenizer) {
- [self handleToken:token];
+ [self processToken:token];
}
return nil;
}
-- (void)handleToken:(HTMLToken *)token
+
+- (void)processToken:(HTMLToken *)token
{
BOOL (^ treeConstructionDispatcher)(HTMLElement *node) = ^BOOL(HTMLElement *node){
@@ -245,13 +263,18 @@
};
if (treeConstructionDispatcher(self.adjustedCurrentNode)) {
- [self handleToken:token byApplyingRulesForInsertionMode:_insertionMode];
+ [self processToken:token byApplyingRulesForInsertionMode:_insertionMode];
} else {
- [self handleTokenByApplyingRulesForParsingTokensInForeignContent:token];
+ [self processTokenByApplyingRulesForParsingTokensInForeignContent:token];
}
}
-- (void)handleToken:(HTMLToken *)token byApplyingRulesForInsertionMode:(HTMLInsertionMode)insertionMode
+- (void)reprocessToken:(HTMLToken *)token
+{
+ [self processToken:token];
+}
+
+- (void)processToken:(HTMLToken *)token byApplyingRulesForInsertionMode:(HTMLInsertionMode)insertionMode
{
SEL selector = [[_insertionModes objectForKey:@(_insertionMode)] pointerValue];
if ([self respondsToSelector:selector]) {
@@ -263,9 +286,49 @@
}
}
-- (void)handleTokenByApplyingRulesForParsingTokensInForeignContent:(HTMLToken *)token
+- (void)processTokenByApplyingRulesForParsingTokensInForeignContent:(HTMLToken *)token
{
+
+#pragma mark -
+
+- (HTMLElement *)appropriatePlaceForInsertingANodeWithOverrideTarget:(id)overrideTarget
+{
+ HTMLElement *target = self.currentNode;
+ if (overrideTarget == nil) {
+ target = overrideTarget;
+ }
+
+ if (_fosterParting && matches(target.tagName, @"table", @"tbody", @"tfoot", @"thead", @"tr")) {
+ HTMLElement *lastTemplate = nil;
+ HTMLElement *lastTable = nil;
+ for (HTMLElement *element in _stackOfOpenElements.reverseObjectEnumerator) {
+ if ([element.tagName isEqualToString:@"template"]) {
+ lastTemplate = element;
+ break;
+ }
+ if ([element.tagName isEqualToString:@"table"]) {
+ lastTable = element;
+ break;
+ }
+ }
+ if (lastTemplate != nil) {
+#warning Implement HTML Template
+ return nil;
+ }
+ if (lastTable == nil) {
+ HTMLElement *htmlElement = _stackOfOpenElements.firstObject;
+ return htmlElement;
+ }
+ if (lastTable.parentNode != nil) {
+ return lastTable.parentNode;
+ }
+ NSUInteger lastTableIndex = [_stackOfOpenElements indexOfObject:lastTable];
+ HTMLElement *previousNode = _stackOfOpenElements[lastTableIndex];
+ return previousNode;
+ } else {
+ return target;
+ }
}
#pragma mark - Insertion Modes
diff --git a/HTMLKit/HTMLParserInsertionModes.h b/HTMLKit/HTMLParserInsertionModes.h
index 7b89ee8..838e164 100644
--- a/HTMLKit/HTMLParserInsertionModes.h
+++ b/HTMLKit/HTMLParserInsertionModes.h
@@ -29,7 +29,9 @@
MODE_ENTRY( HTMLInsertionModeInFrameset, ) \
MODE_ENTRY( HTMLInsertionModeAfterFrameset, ) \
MODE_ENTRY( HTMLInsertionModeAfterAfterBody, ) \
- MODE_ENTRY( HTMLInsertionModeAfterAfterFrameset, )
+ MODE_ENTRY( HTMLInsertionModeAfterAfterFrameset, ) \
+ MODE_ENTRY( HTMLInsertionModeCurrentTemplate, ) \
+ MODE_ENTRY( HTMLInsertionModesCount, )
typedef NS_ENUM(NSUInteger, HTMLInsertionMode)
{
@@ -37,3 +39,9 @@ typedef NS_ENUM(NSUInteger, HTMLInsertionMode)
INSERTION_MODES
#undef MODE_ENTRY
};
+
+static NSString * HTMLInsertionModesTable[] = {
+#define MODE_ENTRY( name, value ) [name] = @#name,
+ INSERTION_MODES
+#undef MODE_ENTRY
+};