Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(492)

Unified Diff: Source/core/css/parser/CSSVariableParser.cpp

Issue 1192983003: CSS Custom Properties (Variables) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: ToT-ed again... Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/css/parser/CSSVariableParser.cpp
diff --git a/Source/core/css/parser/CSSVariableParser.cpp b/Source/core/css/parser/CSSVariableParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96f58449be8ef8ae71f93cde7fee4511774d40cc
--- /dev/null
+++ b/Source/core/css/parser/CSSVariableParser.cpp
@@ -0,0 +1,186 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/css/parser/CSSVariableParser.h"
+
+#include "core/css/parser/CSSParserTokenRange.h"
+#include "core/css/parser/CSSParserValues.h"
+
+namespace blink {
+
+static bool isValidVariableName(const CSSParserToken& token)
+{
+ CSSParserString value = token.value();
+ return value.length() >= 2 && value[0] == '-' && value[0] == value[1];
+}
+
+static bool isValidVariableReference(CSSParserTokenRange& range)
+{
+ bool foundVariableIdentToken = false;
+ bool foundComma = false;
+ bool contentAfterComma = false;
+ unsigned bracketCount = 0;
+ while (!range.atEnd()) {
+ const CSSParserToken& token = range.consume();
+ switch (token.type()) {
+ case WhitespaceToken:
+ if (foundComma)
+ contentAfterComma = true;
+ break;
+ case IdentToken:
+ if (foundComma) {
+ contentAfterComma = true;
+ } else if (!foundVariableIdentToken) {
+ if (!isValidVariableName(token))
+ return false;
+ foundVariableIdentToken = true;
+ } else {
+ return false;
+ }
+ break;
+ case FunctionToken:
+ case LeftParenthesisToken:
+ if (!foundComma)
+ return false;
+ bracketCount++;
+ break;
+ case RightParenthesisToken:
+ if (!foundVariableIdentToken)
+ return false;
+ if (!bracketCount)
+ return foundVariableIdentToken && (!foundComma || contentAfterComma);
+ bracketCount--;
+ break;
+ case CommaToken:
+ if (!foundVariableIdentToken)
+ return false;
+ foundComma = true;
+ break;
+ case CommentToken:
+ case EOFToken:
+ ASSERT_NOT_REACHED();
+ case SemicolonToken:
+ return false;
+ case CDOToken:
+ case CDCToken:
+ case AtKeywordToken:
+ case IncludeMatchToken:
+ case DashMatchToken:
+ case PrefixMatchToken:
+ case SuffixMatchToken:
+ case SubstringMatchToken:
+ case ColumnToken:
+ case BadStringToken:
+ case BadUrlToken:
+ case ColonToken:
+ // TODO(leviw): Need to match CDO/CDC tokens
+ if (!foundComma)
+ return false;
+ break;
+ default:
+ if (!foundComma)
+ return false;
+ break;
+ }
+ }
+ return false;
+}
+
+static CSSVariableParser::DefinitionType classifyVariableRange(const CSSParserTokenRange& originalRange, bool& important)
+{
+ CSSParserTokenRange range = originalRange;
+ CSSVariableParser::DefinitionType type = CSSVariableParser::Variable;
+ bool lastTokenWasExclamation = false;
+
+ // TODO(leviw): this needs to be a stack.
+ bool foundImportant = false;
+
+ int bracketCount = 0;
+
Timothy Loh 2015/07/23 08:11:47 Probably something like: range.consumeWhitespace(
+ while (!range.atEnd()) {
+ const CSSParserToken& token = range.consume();
+ switch (token.type()) {
+ case FunctionToken:
+ if (token.valueEqualsIgnoringCase("var")) {
+ if (!isValidVariableReference(range))
+ return CSSVariableParser::Invalid; // Bail if any references are invalid
+ type = CSSVariableParser::VariableWithReferences;
+ } else {
+ bracketCount++;
+ }
+ lastTokenWasExclamation = false;
+ break;
+ case CommentToken:
+ case EOFToken:
+ ASSERT_NOT_REACHED();
+ case IdentToken:
+ // TODO(leviw): This isn't correct.
+ if (token.valueEqualsIgnoringCase("inherit")) {
+ type = CSSVariableParser::Inherit;
+ } else if (token.valueEqualsIgnoringCase("initial")) {
+ type = CSSVariableParser::Initial;
+ } else if (token.valueEqualsIgnoringCase("unset")) {
+ type = CSSVariableParser::Unset;
+ } else if (lastTokenWasExclamation && token.valueEqualsIgnoringCase("important")) {
Timothy Loh 2015/07/23 08:11:47 Why does this need to handle !important when consu
+ if (foundImportant)
+ return CSSVariableParser::Invalid;
+ foundImportant = true;
+ important = true;
+ }
+ lastTokenWasExclamation = false;
+ break;
+ case DelimiterToken:
+ lastTokenWasExclamation = token.delimiter() == '!';
+ break;
+ case RightParenthesisToken:
+ if (!bracketCount)
+ return CSSVariableParser::Invalid;
+ bracketCount--;
+ break;
+ case LeftParenthesisToken:
+ bracketCount++;
+ break;
+ case SemicolonToken:
+ return CSSVariableParser::Invalid;
+ case CDOToken:
Timothy Loh 2015/07/23 08:11:47 The spec doesn't say these are invalid
+ case CDCToken:
+ case AtKeywordToken:
+ case IncludeMatchToken:
+ case DashMatchToken:
+ case PrefixMatchToken:
+ case SuffixMatchToken:
+ case SubstringMatchToken:
+ case ColumnToken:
+ case BadStringToken:
+ case BadUrlToken:
+ case ColonToken:
+ return CSSVariableParser::Invalid;
+ case WhitespaceToken:
+ break;
+ default:
+ lastTokenWasExclamation = false;
+ break;
+ }
+ }
+ if (bracketCount)
+ return CSSVariableParser::Invalid;
+ return type;
+}
+
+bool CSSVariableParser::containsValidVariableReferences(const CSSParserTokenRange& originalRange)
+{
+ bool important;
+ return VariableWithReferences == classifyVariableRange(originalRange, important);
+}
+
+CSSVariableParser::DefinitionType CSSVariableParser::parseVariableDefinition(const CSSParserTokenRange& originalRange, bool& important)
+{
+ important = false;
+ if (originalRange.atEnd())
+ return CSSVariableParser::Invalid;
+ return classifyVariableRange(originalRange, important);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698