From f0e5a7cb26eea2c6007f9f661bf1e11e0dbe74ae Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 1 Mar 2015 03:31:03 +0100 Subject: [PATCH] Add "Before HTML" & "Before Head" insertion modes implementation in HTML Parser https://html.spec.whatwg.org/multipage/syntax.html#the-before-html-insertion-mode https://html.spec.whatwg.org/multipage/syntax.html#the-before-head-insertion-mode --- HTMLKit/HTMLParser.m | 74 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 4 deletions(-) diff --git a/HTMLKit/HTMLParser.m b/HTMLKit/HTMLParser.m index 3489116..fa5b390 100644 --- a/HTMLKit/HTMLParser.m +++ b/HTMLKit/HTMLParser.m @@ -407,17 +407,13 @@ { switch (token.type) { case HTMLTokenTypeCharacter: - { if ([token.asCharacterToken isWhitespaceToken]) { return; } break; - } case HTMLTokenTypeComment: - { [self insertComment:token.asCommentToken asChildOfNode:_document]; return; - } case HTMLTokenTypeDoctype: { HTMLDOCTYPEToken *doctypeToken = token.asDoctypeToken; @@ -450,12 +446,82 @@ - (void)HTMLInsertionModeBeforeHTML:(HTMLToken *)token { + switch (token.type) { + case HTMLTokenTypeDoctype: + [self emitParseError:@"Unexpected DOCTYPE Token before "]; + return; + case HTMLTokenTypeComment: + [self insertComment:token.asCommentToken asChildOfNode:_document]; + return; + case HTMLTokenTypeCharacter: + if ([token.asCharacterToken isWhitespaceToken]) { + return; + } + break; + case HTMLTokenTypeStartTag: + if ([token.asStartTagToken.tagName isEqualToString:@"html"]) { + HTMLElement *html = [self createElementForToken:token.asTagToken inNamespace:HTMLNamespaceHTML]; + [_document appendChildNode:html]; + [_stackOfOpenElements addObject:html]; + [self switchInsertionMode:HTMLInsertionModeBeforeHead]; + return; + } + break; + case HTMLTokenTypeEndTag: + if (!matches(token.asEndTagToken.tagName, @"head", @"body", @"html", @"br")) { + [self emitParseError:@"Unexpected End Tag Token (%@) before ", token.asEndTagToken.tagName]; + return; + } + break; + default: + break; + } + HTMLElement *html = [[HTMLElement alloc] initWithTagName:@"html"]; + [_document appendChildNode:html]; + [_stackOfOpenElements addObject:html]; + [self switchInsertionMode:HTMLInsertionModeBeforeHead]; + [self reprocessToken:token]; } - (void)HTMLInsertionModeBeforeHead:(HTMLToken *)token { + switch (token.type) { + case HTMLTokenTypeCharacter: + if ([token.asCharacterToken isWhitespaceToken]) { + return; + } + break; + case HTMLTokenTypeComment: + [self insertComment:token.asCommentToken asChildOfNode:_document]; + return; + case HTMLTokenTypeDoctype: + [self emitParseError:@"Unexpected DOCTYPE Token before "]; + return; + case HTMLTokenTypeStartTag: + if ([token.asStartTagToken.tagName isEqualToString:@"html"]) { + [self HTMLInsertionModeInBody:token]; + } else if ([token.asStartTagToken.tagName isEqualToString:@"head"]) { + HTMLElement *head = [[HTMLElement alloc] initWithTagName:@"head"]; + _headElementPointer = head; + [self switchInsertionMode:HTMLInsertionModeInHead]; + } + return; + case HTMLTokenTypeEndTag: + if (!matches(token.asEndTagToken.tagName, @"head", @"body", @"html", @"br")) { + [self emitParseError:@"Unexpected End Tag Token (%@) before ", token.asEndTagToken.tagName]; + return; + } + break; + default: + break; + } + HTMLStartTagToken *headToken = [[HTMLStartTagToken alloc] initWithTagName:@"head"]; + HTMLElement *head = [self insertElementForToken:headToken]; + _headElementPointer = head; + [self switchInsertionMode:HTMLInsertionModeInHead]; + [self reprocessToken:token]; } - (void)HTMLInsertionModeInHead:(HTMLToken *)token