Add initial implementation for "appropriate place for inserting a node"
https://html.spec.whatwg.org/multipage/syntax.html#creating-and-inserting-nodes
This commit is contained in:
@@ -17,4 +17,5 @@
|
||||
|
||||
- (void)appendString:(NSString *)string;
|
||||
|
||||
- (BOOL)isWhitespaceToken;
|
||||
@end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -13,5 +13,6 @@
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *tagName;
|
||||
@property (nonatomic, assign, readonly) HTMLNamespace namespace;
|
||||
@property (nonatomic, strong, readonly) id parentNode;
|
||||
|
||||
@end
|
||||
|
||||
+69
-6
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user