PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSParserTokenRange& range) { OwnPtr<CSSParserSelector> selector; AtomicString namespacePrefix; AtomicString elementName; bool hasNamespace; if (!consumeName(range, elementName, namespacePrefix, hasNamespace)) { selector = consumeSimpleSelector(range); if (!selector) return nullptr; } if (m_context.isHTMLDocument()) elementName = elementName.lower(); while (OwnPtr<CSSParserSelector> nextSelector = consumeSimpleSelector(range)) { if (selector) selector = rewriteSpecifiers(selector.release(), nextSelector.release()); else selector = nextSelector.release(); } if (!selector) { if (hasNamespace) return CSSParserSelector::create(determineNameInNamespace(namespacePrefix, elementName)); return CSSParserSelector::create(QualifiedName(nullAtom, elementName, m_defaultNamespace)); } if (elementName.isNull()) rewriteSpecifiersWithNamespaceIfNeeded(selector.get()); else rewriteSpecifiersWithElementName(namespacePrefix, elementName, selector.get()); return selector.release(); }
CSSParserToken CSSTokenizer::commercialAt(UChar cc) { ASSERT(cc == '@'); if (nextCharsAreIdentifier()) return CSSParserToken(AtKeywordToken, consumeName()); return CSSParserToken(DelimiterToken, '@'); }
// http://www.w3.org/TR/css3-syntax/#consume-an-ident-like-token MediaQueryToken MediaQueryTokenizer::consumeIdentLikeToken() { String name = consumeName(); if (consumeIfNext('(')) { return blockStart(LeftParenthesisToken, FunctionToken, name); } return MediaQueryToken(IdentToken, name); }
// http://www.w3.org/TR/css3-syntax/#consume-a-numeric-token CSSParserToken CSSTokenizer::consumeNumericToken() { CSSParserToken token = consumeNumber(); if (nextCharsAreIdentifier()) token.convertToDimensionWithUnit(consumeName()); else if (consumeIfNext('%')) token.convertToPercentage(); return token; }
CSSParserToken CSSTokenizer::hash(UChar cc) { UChar nextChar = m_input.nextInputChar(); if (isNameChar(nextChar) || twoCharsAreValidEscape(nextChar, m_input.peek(1))) { HashTokenType type = nextCharsAreIdentifier() ? HashTokenId : HashTokenUnrestricted; return CSSParserToken(type, consumeName()); } return CSSParserToken(DelimiterToken, cc); }
std::unique_ptr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector( CSSParserTokenRange& range) { std::unique_ptr<CSSParserSelector> compoundSelector; AtomicString namespacePrefix; AtomicString elementName; CSSSelector::PseudoType compoundPseudoElement = CSSSelector::PseudoUnknown; if (!consumeName(range, elementName, namespacePrefix)) { compoundSelector = consumeSimpleSelector(range); if (!compoundSelector) return nullptr; if (compoundSelector->match() == CSSSelector::PseudoElement) compoundPseudoElement = compoundSelector->pseudoType(); } if (m_context.isHTMLDocument()) elementName = elementName.lower(); while (std::unique_ptr<CSSParserSelector> simpleSelector = consumeSimpleSelector(range)) { // TODO([email protected]): crbug.com/578131 // The UASheetMode check is a work-around to allow this selector in // mediaControls(New).css: // video::-webkit-media-text-track-region-container.scrolling if (m_context.mode() != UASheetMode && !isSimpleSelectorValidAfterPseudoElement(*simpleSelector.get(), compoundPseudoElement)) { m_failedParsing = true; return nullptr; } if (simpleSelector->match() == CSSSelector::PseudoElement) compoundPseudoElement = simpleSelector->pseudoType(); if (compoundSelector) compoundSelector = addSimpleSelectorToCompound( std::move(compoundSelector), std::move(simpleSelector)); else compoundSelector = std::move(simpleSelector); } if (!compoundSelector) { AtomicString namespaceURI = determineNamespace(namespacePrefix); if (namespaceURI.isNull()) { m_failedParsing = true; return nullptr; } if (namespaceURI == defaultNamespace()) namespacePrefix = nullAtom; return CSSParserSelector::create( QualifiedName(namespacePrefix, elementName, namespaceURI)); } prependTypeSelectorIfNeeded(namespacePrefix, elementName, compoundSelector.get()); return splitCompoundAtImplicitShadowCrossingCombinator( std::move(compoundSelector)); }
void DocumentBuilder::consumeElement(Node *root){ consume("<", 1); String *name = consumeName(); Element *el = doc->createElement(name); root->appendChild(el); if (peek(0) == '/' && peek(1) == '>' || peek(0) == '>'){ // no attributes }else{ consumeSpaces(1); while(!(peek(0) == '/' && peek(1) == '>' || peek(0) == '>')){ consumeSpaces(); String *aname = consumeName(); consumeSpaces(); consume("=", 1); consumeSpaces(); String *aval = consumeAttributeValue(); consumeSpaces(); el->setAttribute(aname, aval); } } if (peek(0) == '/' && peek(1) == '>'){ consume("/>", 1); }else{ consume(">", 1); consumeContent(el); consume("</", 2); consume(*name); consumeSpaces(); consume(">", 1); } }
// http://dev.w3.org/csswg/css-syntax/#consume-ident-like-token CSSParserToken CSSTokenizer::consumeIdentLikeToken() { CSSParserString name = consumeName(); if (consumeIfNext('(')) { if (name.equalIgnoringASCIICase("url")) { // The spec is slightly different so as to avoid dropping whitespace // tokens, but they wouldn't be used and this is easier. consumeUntilNonWhitespace(); UChar next = m_input.nextInputChar(); if (next != '"' && next != '\'') return consumeUrlToken(); } return blockStart(LeftParenthesisToken, FunctionToken, name); } return CSSParserToken(IdentToken, name); }
std::unique_ptr<CSSParserSelector> CSSSelectorParser::consumeAttribute( CSSParserTokenRange& range) { ASSERT(range.peek().type() == LeftBracketToken); CSSParserTokenRange block = range.consumeBlock(); block.consumeWhitespace(); AtomicString namespacePrefix; AtomicString attributeName; if (!consumeName(block, attributeName, namespacePrefix)) return nullptr; block.consumeWhitespace(); if (m_context.isHTMLDocument()) attributeName = attributeName.lower(); AtomicString namespaceURI = determineNamespace(namespacePrefix); if (namespaceURI.isNull()) return nullptr; QualifiedName qualifiedName = namespacePrefix.isNull() ? QualifiedName(nullAtom, attributeName, nullAtom) : QualifiedName(namespacePrefix, attributeName, namespaceURI); std::unique_ptr<CSSParserSelector> selector = CSSParserSelector::create(); if (block.atEnd()) { selector->setAttribute(qualifiedName, CSSSelector::CaseSensitive); selector->setMatch(CSSSelector::AttributeSet); return selector; } selector->setMatch(consumeAttributeMatch(block)); const CSSParserToken& attributeValue = block.consumeIncludingWhitespace(); if (attributeValue.type() != IdentToken && attributeValue.type() != StringToken) return nullptr; selector->setValue(attributeValue.value().toAtomicString()); selector->setAttribute(qualifiedName, consumeAttributeFlags(block)); if (!block.atEnd()) return nullptr; return selector; }