📄 htmlparser.cpp
字号:
insertNode(e); handled = true; } } // 3. If we couldn't handle the error, just return false and attempt to error-correct again. if (!handled) { reportError(IgnoredContentError, &localName, &m_current->localName()); return false; } return insertNode(n);}typedef bool (HTMLParser::*CreateErrorCheckFunc)(Token* t, RefPtr<Node>&);typedef HashMap<AtomicStringImpl*, CreateErrorCheckFunc> FunctionMap;bool HTMLParser::textCreateErrorCheck(Token* t, RefPtr<Node>& result){ result = new Text(m_document, t->text.get()); return false;}bool HTMLParser::commentCreateErrorCheck(Token* t, RefPtr<Node>& result){ result = new Comment(m_document, t->text.get()); return false;}bool HTMLParser::headCreateErrorCheck(Token*, RefPtr<Node>& result){ if (!m_head || m_current->localName() == htmlTag) { m_head = new HTMLHeadElement(headTag, m_document); result = m_head; } else reportError(MisplacedHeadError); return false;}bool HTMLParser::bodyCreateErrorCheck(Token*, RefPtr<Node>&){ // body no longer allowed if we have a frameset if (m_haveFrameSet) return false; popBlock(headTag); startBody(); return true;}bool HTMLParser::framesetCreateErrorCheck(Token*, RefPtr<Node>&){ popBlock(headTag); if (m_inBody && !m_haveFrameSet && !m_haveContent) { popBlock(bodyTag); // ### actually for IE document.body returns the now hidden "body" element // we can't implement that behaviour now because it could cause too many // regressions and the headaches are not worth the work as long as there is // no site actually relying on that detail (Dirk) if (m_document->body()) m_document->body()->setAttribute(styleAttr, "display:none"); m_inBody = false; } if ((m_haveContent || m_haveFrameSet) && m_current->localName() == htmlTag) return false; m_haveFrameSet = true; startBody(); return true;}bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result){ // Only create a new form if we're not already inside one. // This is consistent with other browsers' behavior. if (!m_currentFormElement) { m_currentFormElement = new HTMLFormElement(formTag, m_document); result = m_currentFormElement; pCloserCreateErrorCheck(t, result); } return false;}bool HTMLParser::isindexCreateErrorCheck(Token* t, RefPtr<Node>& result){ RefPtr<Node> n = handleIsindex(t); if (!m_inBody) m_isindexElement = n.release(); else { t->selfClosingTag = true; result = n.release(); } return false;}bool HTMLParser::selectCreateErrorCheck(Token*, RefPtr<Node>&){ return true;}bool HTMLParser::ddCreateErrorCheck(Token* t, RefPtr<Node>& result){ pCloserCreateErrorCheck(t, result); popBlock(dtTag); popBlock(ddTag); return true;}bool HTMLParser::dtCreateErrorCheck(Token* t, RefPtr<Node>& result){ pCloserCreateErrorCheck(t, result); popBlock(ddTag); popBlock(dtTag); return true;}bool HTMLParser::nestedCreateErrorCheck(Token* t, RefPtr<Node>&){ popBlock(t->tagName); return true;}bool HTMLParser::nestedPCloserCreateErrorCheck(Token* t, RefPtr<Node>& result){ pCloserCreateErrorCheck(t, result); popBlock(t->tagName); return true;}bool HTMLParser::nestedStyleCreateErrorCheck(Token* t, RefPtr<Node>&){ return allowNestedRedundantTag(t->tagName);}bool HTMLParser::tableCellCreateErrorCheck(Token*, RefPtr<Node>&){ popBlock(tdTag); popBlock(thTag); return true;}bool HTMLParser::tableSectionCreateErrorCheck(Token*, RefPtr<Node>&){ popBlock(theadTag); popBlock(tbodyTag); popBlock(tfootTag); return true;}bool HTMLParser::noembedCreateErrorCheck(Token*, RefPtr<Node>&){ setSkipMode(noembedTag); return true;}bool HTMLParser::noframesCreateErrorCheck(Token*, RefPtr<Node>&){ setSkipMode(noframesTag); return true;}bool HTMLParser::noscriptCreateErrorCheck(Token*, RefPtr<Node>&){ if (!m_isParsingFragment) { Settings* settings = m_document->settings(); if (settings && settings->isJavaScriptEnabled()) setSkipMode(noscriptTag); } return true;}bool HTMLParser::pCloserCreateErrorCheck(Token*, RefPtr<Node>&){ if (hasPElementInScope()) popBlock(pTag); return true;}bool HTMLParser::pCloserStrictCreateErrorCheck(Token*, RefPtr<Node>&){ if (m_document->inCompatMode()) return true; if (hasPElementInScope()) popBlock(pTag); return true;}bool HTMLParser::mapCreateErrorCheck(Token*, RefPtr<Node>& result){ m_currentMapElement = new HTMLMapElement(mapTag, m_document); result = m_currentMapElement; return false;}PassRefPtr<Node> HTMLParser::getNode(Token* t){ // Init our error handling table. DEFINE_STATIC_LOCAL(FunctionMap, gFunctionMap, ()); if (gFunctionMap.isEmpty()) { gFunctionMap.set(aTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); gFunctionMap.set(addressTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(bTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(bigTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(blockquoteTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(bodyTag.localName().impl(), &HTMLParser::bodyCreateErrorCheck); gFunctionMap.set(buttonTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); gFunctionMap.set(centerTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(commentAtom.impl(), &HTMLParser::commentCreateErrorCheck); gFunctionMap.set(ddTag.localName().impl(), &HTMLParser::ddCreateErrorCheck); gFunctionMap.set(dirTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(divTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(dlTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(dtTag.localName().impl(), &HTMLParser::dtCreateErrorCheck); gFunctionMap.set(formTag.localName().impl(), &HTMLParser::formCreateErrorCheck); gFunctionMap.set(fieldsetTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(framesetTag.localName().impl(), &HTMLParser::framesetCreateErrorCheck); gFunctionMap.set(h1Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(h2Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(h3Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(h4Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(h5Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(h6Tag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(headTag.localName().impl(), &HTMLParser::headCreateErrorCheck); gFunctionMap.set(hrTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(iTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(isindexTag.localName().impl(), &HTMLParser::isindexCreateErrorCheck); gFunctionMap.set(liTag.localName().impl(), &HTMLParser::nestedPCloserCreateErrorCheck); gFunctionMap.set(listingTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(mapTag.localName().impl(), &HTMLParser::mapCreateErrorCheck); gFunctionMap.set(menuTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(nobrTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); gFunctionMap.set(noembedTag.localName().impl(), &HTMLParser::noembedCreateErrorCheck); gFunctionMap.set(noframesTag.localName().impl(), &HTMLParser::noframesCreateErrorCheck); gFunctionMap.set(noscriptTag.localName().impl(), &HTMLParser::noscriptCreateErrorCheck); gFunctionMap.set(olTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(pTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(plaintextTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(preTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); gFunctionMap.set(sTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(selectTag.localName().impl(), &HTMLParser::selectCreateErrorCheck); gFunctionMap.set(smallTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(strikeTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(tableTag.localName().impl(), &HTMLParser::pCloserStrictCreateErrorCheck); gFunctionMap.set(tbodyTag.localName().impl(), &HTMLParser::tableSectionCreateErrorCheck); gFunctionMap.set(tdTag.localName().impl(), &HTMLParser::tableCellCreateErrorCheck); gFunctionMap.set(textAtom.impl(), &HTMLParser::textCreateErrorCheck); gFunctionMap.set(tfootTag.localName().impl(), &HTMLParser::tableSectionCreateErrorCheck); gFunctionMap.set(thTag.localName().impl(), &HTMLParser::tableCellCreateErrorCheck); gFunctionMap.set(theadTag.localName().impl(), &HTMLParser::tableSectionCreateErrorCheck); gFunctionMap.set(trTag.localName().impl(), &HTMLParser::nestedCreateErrorCheck); gFunctionMap.set(ttTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(uTag.localName().impl(), &HTMLParser::nestedStyleCreateErrorCheck); gFunctionMap.set(ulTag.localName().impl(), &HTMLParser::pCloserCreateErrorCheck); } bool proceed = true; RefPtr<Node> result; if (CreateErrorCheckFunc errorCheckFunc = gFunctionMap.get(t->tagName.impl())) proceed = (this->*errorCheckFunc)(t, result); if (proceed) result = HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, t->tagName, xhtmlNamespaceURI), m_document, m_currentFormElement.get()); return result.release();}bool HTMLParser::allowNestedRedundantTag(const AtomicString& tagName){ // www.liceo.edu.mx is an example of a site that achieves a level of nesting of // about 1500 tags, all from a bunch of <b>s. We will only allow at most 20 // nested tags of the same type before just ignoring them all together. unsigned i = 0; for (HTMLStackElem* curr = m_blockStack; i < cMaxRedundantTagDepth && curr && curr->tagName == tagName; curr = curr->next, i++) { } return i != cMaxRedundantTagDepth;}void HTMLParser::processCloseTag(Token* t){ // Support for really broken html. // we never close the body tag, since some stupid web pages close it before the actual end of the doc. // let's rely on the end() call to close things. if (t->tagName == htmlTag || t->tagName == bodyTag || t->tagName == commentAtom) return; bool checkForCloseTagErrors = true; if (t->tagName == formTag && m_currentFormElement) { m_currentFormElement = 0; checkForCloseTagErrors = false; } else if (t->tagName == mapTag) m_currentMapElement = 0; else if (t->tagName == pTag) checkForCloseTagErrors = false; HTMLStackElem* oldElem = m_blockStack; popBlock(t->tagName, checkForCloseTagErrors); if (oldElem == m_blockStack && t->tagName == pTag) { // We encountered a stray </p>. Amazingly Gecko, WinIE, and MacIE all treat // this as a valid break, i.e., <p></p>. So go ahead and make the empty // paragraph. t->beginTag = true; parseToken(t); popBlock(t->tagName); reportError(StrayParagraphCloseError); }}bool HTMLParser::isHeaderTag(const AtomicString& tagName){ DEFINE_STATIC_LOCAL(HashSet<AtomicStringImpl*>, headerTags, ()); if (headerTags.isEmpty()) { headerTags.add(h1Tag.localName().impl()); headerTags.add(h2Tag.localName().impl()); headerTags.add(h3Tag.localName().impl()); headerTags.add(h4Tag.localName().impl()); headerTags.add(h5Tag.localName().impl()); headerTags.add(h6Tag.localName().impl()); } return headerTags.contains(tagName.impl());}bool HTMLParser::isInline(Node* node) const{ if (node->isTextNode()) return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -