/*
* Copyright 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.template.soy.soytree;
import javax.annotation.Nullable;
/**
* The type of HTML (or non-HTML) that contains a Soy node. This is primarily used by the contextual
* auto-escaper to add escaping directives. It's also used by incremental DOM's HTML parser to mark
* nodes for other passes to consume.
*/
public enum HtmlContext {
/** Outside an HTML tag, directive, or comment. (Parsed character data). */
HTML_PCDATA(EscapingMode.ESCAPE_HTML),
/**
* Inside an element whose content is RCDATA where text and entities can appear but where nested
* elements cannot. The content of {@code <title>} and {@code <textarea>} fall into this category
* since they cannot contain nested elements in HTML.
*/
HTML_RCDATA(EscapingMode.ESCAPE_HTML_RCDATA),
/** Just before a tag name on an open tag. */
HTML_BEFORE_OPEN_TAG_NAME(EscapingMode.FILTER_HTML_ELEMENT_NAME),
/** Just before a tag name on an close tag. */
HTML_BEFORE_CLOSE_TAG_NAME(EscapingMode.FILTER_HTML_ELEMENT_NAME),
/**
* Just after a tag name, e.g. in ^ in <script^> or <div^>.
*
* <p>Note tag names must be printed all at once since we can't otherwise easily handle <s{if
* 1}cript{/if}>.
*/
HTML_TAG_NAME(
"Dynamic values are not permitted in the middle of an HTML tag name;"
+ " try adding a space before."),
/** Before an HTML attribute or the end of a tag. */
HTML_TAG(EscapingMode.FILTER_HTML_ATTRIBUTES),
// TODO: Do we need to filter out names that look like JS/CSS/URI attribute names.
/** Inside an HTML attribute name. */
HTML_ATTRIBUTE_NAME(EscapingMode.FILTER_HTML_ATTRIBUTES),
/** Following an equals sign (<tt>=</tt>) after an attribute name in an HTML tag. */
HTML_BEFORE_ATTRIBUTE_VALUE("(unexpected state)"),
/** Inside an HTML comment. */
HTML_COMMENT(EscapingMode.ESCAPE_HTML_RCDATA),
/** Inside a normal (non-CSS, JS, or URI) HTML attribute value. */
HTML_NORMAL_ATTR_VALUE(EscapingMode.ESCAPE_HTML_ATTRIBUTE),
/** In CSS content outside a comment, string, or URI. */
CSS(EscapingMode.FILTER_CSS_VALUE),
/** In CSS inside a comment. */
CSS_COMMENT("CSS comments cannot contain dynamic values."),
/** In CSS inside a double quoted string. */
CSS_DQ_STRING(EscapingMode.ESCAPE_CSS_STRING),
/** In CSS inside a single quoted string. */
CSS_SQ_STRING(EscapingMode.ESCAPE_CSS_STRING),
/** In CSS in a URI terminated by the first close parenthesis. */
CSS_URI(EscapingMode.NORMALIZE_URI),
/** In CSS in a URI terminated by the first double quote. */
CSS_DQ_URI(EscapingMode.NORMALIZE_URI),
/** In CSS in a URI terminated by the first single quote. */
CSS_SQ_URI(EscapingMode.NORMALIZE_URI),
/** In JavaScript, outside a comment, string, or Regexp literal. */
JS(EscapingMode.ESCAPE_JS_VALUE),
/** In JavaScript inside a line comment. */
JS_LINE_COMMENT("JS comments cannot contain dynamic values."),
/** In JavaScript inside a block comment. */
JS_BLOCK_COMMENT("JS comments cannot contain dynamic values."),
/** In JavaScript inside a double quoted string. */
JS_DQ_STRING(EscapingMode.ESCAPE_JS_STRING),
/** In JavaScript inside a single quoted string. */
JS_SQ_STRING(EscapingMode.ESCAPE_JS_STRING),
/** In JavaScript inside a regular expression literal. */
JS_REGEX(EscapingMode.ESCAPE_JS_REGEX),
/** In a URI, which may or may not be in an HTML attribute. */
URI(EscapingMode.NORMALIZE_URI),
/** Plain text; no escaping. */
TEXT(EscapingMode.TEXT);
@Nullable private final EscapingMode escapingMode;
@Nullable private final String errorMessage;
/**
* The escaping mode appropriate for dynamic content inserted at this state. Null if there is no
* appropriate escaping convention to use as for comments or plain text which do not have escaping
* conventions.
*/
public EscapingMode getEscapingMode() {
return escapingMode;
}
/** Error message to show when trying to print a dynamic value inside of this state. */
public String getErrorMessage() {
return errorMessage;
}
HtmlContext(EscapingMode escapingMode) {
this.escapingMode = escapingMode;
this.errorMessage = null;
}
HtmlContext(String errorMessage) {
this.errorMessage = errorMessage;
this.escapingMode = null;
}
}