Add wrapper class for the "list of active formatting elements"

This commit is contained in:
iska
2015-03-22 15:07:40 +01:00
parent 8e427cbb3f
commit d9dade5fb0
4 changed files with 194 additions and 39 deletions
+10
View File
@@ -25,6 +25,9 @@
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 */; };
62363C3D1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */; };
62363C3E1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */; };
62363C3F1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */; };
6238039F1AB63A8C008A53D0 /* HTMLEOFToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 6238039D1AB63A8C008A53D0 /* HTMLEOFToken.h */; };
623803A01AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238039E1AB63A8C008A53D0 /* HTMLEOFToken.m */; };
623803A11AB63A8C008A53D0 /* HTMLEOFToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 6238039E1AB63A8C008A53D0 /* HTMLEOFToken.m */; };
@@ -146,6 +149,8 @@
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>"; };
62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLListOfActiveFormattingElements.h; sourceTree = "<group>"; };
62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLListOfActiveFormattingElements.m; sourceTree = "<group>"; };
623719431AA12EE8002E03C8 /* HTMLQuirksMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLQuirksMode.h; sourceTree = "<group>"; };
6238039D1AB63A8C008A53D0 /* HTMLEOFToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLEOFToken.h; sourceTree = "<group>"; };
6238039E1AB63A8C008A53D0 /* HTMLEOFToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLEOFToken.m; sourceTree = "<group>"; };
@@ -323,6 +328,8 @@
62F873EA19E088C90062683C /* HTMLParser.m */,
6234BEEC1AABBF1400DEB15F /* HTMLStackOfOpenElements.h */,
6234BEED1AABBF1400DEB15F /* HTMLStackOfOpenElements.m */,
62363C3B1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h */,
62363C3C1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m */,
628B7CE61A080E1000602C87 /* HTMLNamespaces.h */,
6223211D1A969B9300BACED5 /* HTMLElementTypes.h */,
6234C3361AB3BF710046F527 /* HTMLElementAdjustment.h */,
@@ -436,6 +443,7 @@
62AE593519F97D880043F069 /* HTMLParseErrorToken.h in Headers */,
62AE594919F9948A0043F069 /* HTMLCharacterToken.h in Headers */,
623857961A9E8606003A45D9 /* HTMLDocumentType.h in Headers */,
62363C3D1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.h in Headers */,
62362A3C1A9FA70400301989 /* HTMLText.h in Headers */,
6234584E1A9D2FA4009BD491 /* HTMLNode.h in Headers */,
);
@@ -596,6 +604,7 @@
6234248A1AB467B200726190 /* HTMLOrderedDictionary.m in Sources */,
62AE594119F9907C0043F069 /* HTMLTagToken.m in Sources */,
62AE594619F992F30043F069 /* HTMLCommentToken.m in Sources */,
62363C3F1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */,
62AE593C19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */,
6238C9871AB8D6330006512E /* HTMLKitExceptions.m in Sources */,
62F873ED19E088C90062683C /* HTMLParser.m in Sources */,
@@ -636,6 +645,7 @@
623424891AB467B200726190 /* HTMLOrderedDictionary.m in Sources */,
62AE594019F9907C0043F069 /* HTMLTagToken.m in Sources */,
62AE594519F992F30043F069 /* HTMLCommentToken.m in Sources */,
62363C3E1ABE428200DAB4C6 /* HTMLListOfActiveFormattingElements.m in Sources */,
62AE593B19F97E1C0043F069 /* HTMLDOCTYPEToken.m in Sources */,
6238C9861AB8D6330006512E /* HTMLKitExceptions.m in Sources */,
62F873EC19E088C90062683C /* HTMLParser.m in Sources */,
@@ -0,0 +1,36 @@
//
// HTMLListOfActiveFormattingElements.h
// HTMLKit
//
// Created by Iska on 22/03/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HTMLElement.h"
@interface HTMLListOfActiveFormattingElements : NSObject
- (id)objectAtIndexedSubscript:(NSUInteger)index;
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
- (NSUInteger)indexOfElement:(id)node;
- (void)addElement:(HTMLElement *)element;
- (void)removeElement:(id)element;
- (BOOL)containsElement:(id)element;
- (void)insertElement:(HTMLElement *)element atIndex:(NSUInteger)index;
- (void)replaceElementAtIndex:(NSUInteger)index withElement:(HTMLElement *)element;
- (id)lastEntry;
- (void)addMarker;
- (void)clearUptoLastMarker;
- (NSUInteger)count;
- (BOOL)isEmpty;
- (NSEnumerator *)enumerator;
- (NSEnumerator *)reverseObjectEnumerator;
@end
@@ -0,0 +1,122 @@
//
// HTMLListOfActiveFormattingElements.m
// HTMLKit
//
// Created by Iska on 22/03/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import "HTMLListOfActiveFormattingElements.h"
#import "HTMLMarker.h"
@interface HTMLListOfActiveFormattingElements ()
{
NSMutableArray *_list;
}
@end
@implementation HTMLListOfActiveFormattingElements
- (instancetype)init
{
self = [super init];
if (self) {
_list = [NSMutableArray new];
}
return self;
}
#pragma mark - Access
- (id)objectAtIndexedSubscript:(NSUInteger)index;
{
return [_list objectAtIndex:index];
}
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx
{
[_list setObject:obj atIndexedSubscript:idx];
}
- (NSUInteger)indexOfElement:(id)node
{
return [_list indexOfObject:node];
}
- (void)addElement:(HTMLElement *)element
{
[_list addObject:element];
}
- (void)removeElement:(id)element
{
[_list removeObject:element];
}
- (BOOL)containsElement:(id)element
{
return [_list containsObject:element];
}
- (void)insertElement:(HTMLElement *)element atIndex:(NSUInteger)index
{
[_list insertObject:element atIndex:index];
}
- (void)replaceElementAtIndex:(NSUInteger)index withElement:(HTMLElement *)element
{
[_list replaceObjectAtIndex:index withObject:element];
}
- (id)lastEntry
{
return _list.lastObject;
}
#pragma mark - Acrions
- (void)addMarker
{
[_list addObject:[HTMLMarker marker]];
}
- (void)clearUptoLastMarker
{
while (_list.lastObject != [HTMLMarker marker]) {
[_list removeLastObject];
}
[_list removeLastObject];
}
#pragma mark - Count
- (NSUInteger)count
{
return _list.count;
}
- (BOOL)isEmpty
{
return _list.count == 0;
}
#pragma mark - Enumeraiton
- (NSEnumerator *)enumerator
{
return _list.objectEnumerator;
}
- (NSEnumerator *)reverseObjectEnumerator
{
return _list.reverseObjectEnumerator;
}
#pragma mark - NSFastEnumeration
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len
{
return [_list countByEnumeratingWithState:state objects:buffer count:len];
}
@end
+26 -39
View File
@@ -10,6 +10,7 @@
#import "HTMLTokenizer.h"
#import "HTMLTokens.h"
#import "HTMLStackOfOpenElements.h"
#import "HTMLListOfActiveFormattingElements.h"
#import "HTMLParserInsertionModes.h"
#import "HTMLNodes.h"
#import "HTMLElementTypes.h"
@@ -36,7 +37,7 @@
HTMLInsertionMode _originalInsertionMode;
HTMLStackOfOpenElements *_stackOfOpenElements;
NSMutableArray *_listOfActiveFormattingElements;
HTMLListOfActiveFormattingElements *_listOfActiveFormattingElements;
HTMLDocument *_document;
@@ -70,7 +71,8 @@
[self setupStateMachine];
_stackOfOpenElements = [HTMLStackOfOpenElements new];
_listOfActiveFormattingElements = [NSMutableArray new];
_listOfActiveFormattingElements = [HTMLListOfActiveFormattingElements new];
_tokenizer = [[HTMLTokenizer alloc] initWithString:string];
_tokenizer.parser = self;
@@ -337,11 +339,11 @@
- (void)reconstructActiveFormattingElements
{
if (_listOfActiveFormattingElements.count == 0) {
if (_listOfActiveFormattingElements.isEmpty) {
return;
}
id last = _listOfActiveFormattingElements.lastObject;
id last = _listOfActiveFormattingElements.lastEntry;
if (last == [HTMLMarker marker] || [_stackOfOpenElements constainsElement:last]) {
return;
}
@@ -362,7 +364,7 @@
HTMLStartTagToken *token = [[HTMLStartTagToken alloc] initWithTagName:entry.tagName
attributes:entry.attributes];
HTMLElement *element = [self insertElementForToken:token];
[_listOfActiveFormattingElements replaceObjectAtIndex:index withObject:element];
[_listOfActiveFormattingElements replaceElementAtIndex:index withElement:element];
if (index++ != _listOfActiveFormattingElements.count) {
advance();
}
@@ -381,13 +383,6 @@
rewind();
}
- (void)clearListOfActiveFormattingElementsUptoLastMarker
{
while (_listOfActiveFormattingElements.lastObject != [HTMLMarker marker]) {
[_listOfActiveFormattingElements removeLastObject];
}
}
- (void)generateImpliedEndTagsExceptForElement:(NSString *)tagName
{
while ([self.currentNode.tagName isEqualToAny:@"dd", @"dt", @"li", @"option", @"optgroup", @"p", @"rp", @"rt", nil] &&
@@ -407,8 +402,8 @@
- (BOOL)runAdoptionAgencyAlgorithmForTagName:(NSString *)tagName
{
if ([self.currentNode.tagName isEqualTo:tagName] &&
![_listOfActiveFormattingElements containsObject:self.currentNode]) {
if ([self.currentNode.tagName isEqualToString:tagName] &&
![_listOfActiveFormattingElements containsElement:self.currentNode]) {
[_stackOfOpenElements popCurrentNode];
return NO;
}
@@ -431,7 +426,7 @@
if (![_stackOfOpenElements constainsElement:formattingElement]) {
[self emitParseError:@"Formatting element is not in the Stack of Open Elements"];
[_listOfActiveFormattingElements removeObject:formattingElement];
[_listOfActiveFormattingElements removeElement:formattingElement];
return NO;
}
@@ -458,22 +453,22 @@
if (furthestBlock == nil) {
[_stackOfOpenElements popElementsUntilElementPopped:formattingElement];
[_listOfActiveFormattingElements removeObject:formattingElement];
[_listOfActiveFormattingElements removeElement:formattingElement];
return NO;
}
HTMLElement *commonAncestor = _stackOfOpenElements[formattingElementIndex - 1];
NSUInteger bookmark = [_listOfActiveFormattingElements indexOfObject:formattingElement];
NSUInteger bookmark = [_listOfActiveFormattingElements indexOfElement:formattingElement];
HTMLElement *node = furthestBlock;
HTMLElement *lastNode = furthestBlock;
for (int innerLoopCounter = 0; innerLoopCounter < 3; innerLoopCounter ++) {
NSUInteger nodeStackIndex = [_stackOfOpenElements indexOfElement:node];
NSUInteger nodeListIndex = [_listOfActiveFormattingElements indexOfObject:node];
NSUInteger stackIndex = [_stackOfOpenElements indexOfElement:node];
node = _stackOfOpenElements[nodeStackIndex - 1];
if (![_listOfActiveFormattingElements containsObject:node]) {
if (![_listOfActiveFormattingElements containsElement:node]) {
[_stackOfOpenElements removeElement:node];
continue;
}
@@ -483,8 +478,8 @@
}
HTMLElement *newElement = [node copy];
[_listOfActiveFormattingElements replaceObjectAtIndex:nodeListIndex withObject:newElement];
[_stackOfOpenElements replaceElementAtIndex:nodeStackIndex withElement:newElement];
[_listOfActiveFormattingElements replaceElementAtIndex:listIndex withElement:newElement];
[_stackOfOpenElements replaceElementAtIndex:stackIndex withElement:newElement];
node = newElement;
if ([lastNode isEqual:furthestBlock]) {
@@ -506,8 +501,8 @@
}
[furthestBlock appendNode:newElement];
[_listOfActiveFormattingElements removeObject:formattingElement];
[_listOfActiveFormattingElements insertObject:newElement atIndex:bookmark];
[_listOfActiveFormattingElements removeElement:formattingElement];
[_listOfActiveFormattingElements insertElement:newElement atIndex:bookmark-1];
[_stackOfOpenElements removeElement:formattingElement];
NSUInteger furthestBlockIndex = [_stackOfOpenElements indexOfElement:furthestBlock];
[_stackOfOpenElements insertElement:newElement atIndex:furthestBlockIndex];
@@ -515,14 +510,6 @@
return NO;
}
- (void)clearListOfActiveFormattingElementsUpToLastMarker
{
while (![_listOfActiveFormattingElements.lastObject isEqual:[HTMLMarker marker]]) {
[_listOfActiveFormattingElements removeLastObject];
}
[_listOfActiveFormattingElements removeLastObject];
}
- (void)closeTheCell
{
[self generateImpliedEndTagsExceptForElement:nil];
@@ -530,7 +517,7 @@
[self emitParseError:@"Misnested Cell"];
}
[_stackOfOpenElements popElementsUntilAnElementPoppedWithAnyOfTagNames:@[@"td", @"th"]];
[self clearListOfActiveFormattingElementsUpToLastMarker];
[_listOfActiveFormattingElements clearUptoLastMarker];
[self switchInsertionMode:HTMLInsertionModeInRow];
}
@@ -1169,17 +1156,17 @@
[self processAnyOtherEndTagTokenInBody:token.asTagToken];
return;
}
[_listOfActiveFormattingElements removeObject:element];
[_listOfActiveFormattingElements removeElement:element];
[_stackOfOpenElements removeElement:element];
}
[self reconstructActiveFormattingElements];
HTMLElement *a = [self insertElementForToken:token];
[_listOfActiveFormattingElements addObject:a];
[_listOfActiveFormattingElements addElement:a];
} else if ([tagName isEqualToAny:@"b", @"big", @"code", @"em", @"font", @"i", @"s", @"small",
@"strike", @"strong", @"tt", @"u", nil]) {
[self reconstructActiveFormattingElements];
HTMLElement *element = [self insertElementForToken:token];
[_listOfActiveFormattingElements addObject:element];
[_listOfActiveFormattingElements addElement:element];
} else if ([tagName isEqualToString:@"nobr"]) {
[self reconstructActiveFormattingElements];
if ([_stackOfOpenElements hasElementInScopeWithTagName:@"nobr"]) {
@@ -1456,7 +1443,7 @@
[self emitParseError:@"Unexpected nested (%@) element in <body>", tagName];
}
[_stackOfOpenElements popElementsUntilAnElementPoppedWithAnyOfTagNames:@[@"applet", @"marquee", @"object"]];
[self clearListOfActiveFormattingElementsUpToLastMarker];
[_listOfActiveFormattingElements clearUptoLastMarker];
} else if ([tagName isEqualToString:@"br"]) {
[self emitParseError:@"Unexpected End Tag Token (br) in <body>"];
HTMLStartTagToken *brToken = [[HTMLStartTagToken alloc] initWithTagName:@"br"];
@@ -1658,7 +1645,7 @@
[self emitParseError:@"Unexpected nested (caption) element in <caption>"];
}
[_stackOfOpenElements popElementsUntilElementPoppedWithTagName:@"caption"];
[self clearListOfActiveFormattingElementsUpToLastMarker];
[_listOfActiveFormattingElements clearUptoLastMarker];
[self switchInsertionMode:HTMLInsertionModeInTable];
if (reprocess) {
@@ -1839,7 +1826,7 @@
[_stackOfOpenElements clearBackToTableContext];
[self insertElementForToken:token.asTagToken];
[self switchInsertionMode:HTMLInsertionModeInCell];
[_listOfActiveFormattingElements addObject:[HTMLMarker marker]];
[_listOfActiveFormattingElements addMarker];
} else if ([token.asTagToken.tagName isEqualToAny:@"caption", @"col", @"colgroup", @"tbody",
@"tfoot", @"thead", @"tr", nil]) {
common(@"tr", YES);
@@ -1882,7 +1869,7 @@
[self emitParseError:@"Unexpected nested (%@) element in <td>", token.asTagToken.tagName];
}
[_stackOfOpenElements popElementsUntilElementPoppedWithTagName:token.asTagToken.tagName];
[self clearListOfActiveFormattingElementsUpToLastMarker];
[_listOfActiveFormattingElements clearUptoLastMarker];
[self switchInsertionMode:HTMLInsertionModeInRow];
}
} else if ([token.asTagToken.tagName isEqualToAny:@"body", @"caption", @"col", @"colgroup",