@Override public String apply(SoyValue soyValue) { return soyValue.stringValue(); } };
/** * Converts the input to a JavaScript expression. The resulting expression can be a boolean, * number, string literal, or {@code null}. */ public static String escapeJsValue(SoyValue value) { // We surround values with spaces so that they can't be interpolated into identifiers // by accident. We could use parentheses but those might be interpreted as a function call. if (NullData.INSTANCE == value || value == null) { // The JS counterpart of this code in soyutils.js emits " null " for both null and the special // JS value undefined. return " null "; } else if (value instanceof NumberData) { // This will emit references to NaN and Infinity. Client code should not redefine those // to store sensitive data. return " " + value.numberValue() + " "; } else if (value instanceof BooleanData) { return " " + value.booleanValue() + " "; } else if (isSanitizedContentOfKind(value, SanitizedContent.ContentKind.JS)) { String jsCode = value.coerceToString(); // This value may not be embeddable if it contains the substring "</script". // TODO(msamuel): Fixup. We need to be careful because mucking with '<' can // break code like // while (i</foo/.exec(str).length) // and mucking with / can break // return untrustedHTML.replace(/</g, '<'); return jsCode; } else { return escapeJsValue(value.coerceToString()); } }
@Override Object protoFromSoy(SoyValue field) { return (float) field.floatValue(); } };
/** Performs the {@code <} operator on the two values. */ public static boolean lessThan(SoyValue left, SoyValue right) { if (left instanceof SoyString && right instanceof SoyString) { return left.stringValue().compareTo(right.stringValue()) < 0; } else if (left instanceof IntegerData && right instanceof IntegerData) { return left.longValue() < right.longValue(); } else { return left.numberValue() < right.numberValue(); } }
/** Rounds the given value to the closest integer. */ public static long round(SoyValue value) { if (value instanceof IntegerData) { return value.longValue(); } else { return Math.round(value.numberValue()); } }
/** Performs the {@code +} operator on the two values. */ public static SoyValue plus(SoyValue operand0, SoyValue operand1) { if (operand0 instanceof IntegerData && operand1 instanceof IntegerData) { return IntegerData.forValue(operand0.longValue() + operand1.longValue()); } else if (operand0 instanceof NumberData && operand1 instanceof NumberData) { return FloatData.forValue(operand0.numberValue() + operand1.numberValue()); } else { // String concatenation is the fallback for other types (like in JS). Use the implemented // coerceToString() for the type. return StringData.forValue(operand0.coerceToString() + operand1.coerceToString()); } }
@Override public SoyValue applyForJava(SoyValue value, List<SoyValue> args) { int maxLen; try { maxLen = args.get(0).integerValue(); } catch (SoyDataException sde) { throw new IllegalArgumentException( "Could not parse first parameter of '|truncate' as integer (value was \"" + args.get(0).stringValue() + "\")."); } String str = value.coerceToString(); boolean doAddEllipsis; if (args.size() == 2) { try { doAddEllipsis = args.get(1).booleanValue(); } catch (SoyDataException sde) { throw new IllegalArgumentException( "Could not parse second parameter of '|truncate' as boolean."); } } else { doAddEllipsis = true; // default to true } return StringData.forValue(BasicDirectivesRuntime.truncate(str, maxLen, doAddEllipsis)); }
/** * Gets the integer index out of a SoyValue key, or throws SoyDataException if the key is not an * integer. * * @param key The SoyValue key. * @return The index. */ protected final int getIntegerIndex(SoyValue key) { if (key instanceof StringData) { try { // TODO(gboyer): Remove this case as non-compliant code is fixed. However, since this works // in Javascript, it is particularly difficult to fix callers. (internal) b/11416037 return Integer.parseInt(key.stringValue()); } catch (IllegalArgumentException e) { throw new SoyDataException("\"" + key + "\" is not a valid list index (must be an int)"); } } else { return key.integerValue(); } }
@Override public JavaValue coerceToSoyBoolean() { return TofuJavaValue.forSoyValue( BooleanData.forValue(soyValue.coerceToBoolean()), sourceLocation); }
/** Converts the input to HTML by entity escaping. */ public static String escapeHtml(SoyValue value) { value = normalizeNull(value); if (isSanitizedContentOfKind(value, SanitizedContent.ContentKind.HTML)) { return value.coerceToString(); } return escapeHtml(value.coerceToString()); }
@Override public SoyValue applyForJava(SoyValue value, List<SoyValue> args) { int maxCharsBetweenWordBreaks; try { maxCharsBetweenWordBreaks = args.get(0).integerValue(); } catch (SoyDataException sde) { throw new IllegalArgumentException( "Could not parse 'insertWordBreaks' parameter as integer."); } return BasicDirectivesRuntime.insertWordBreaks(value, maxCharsBetweenWordBreaks); }
@Override Object protoFromSoy(SoyValue field) { return field.booleanValue(); } };
/** Performs the unary negation {@code -} operator on the value. */ public static NumberData negative(SoyValue node) { if (node instanceof IntegerData) { return IntegerData.forValue(-node.longValue()); } else { return FloatData.forValue(-node.floatValue()); } }
@Override Object protoFromSoy(SoyValue field) { return field.longValue(); } };
if (caseExprValue == null) { hasAllNonmatchingConstants = false; } else if (caseExprValue.equals(switchExprValue)) { hasMatchingConstant = true; hasAllNonmatchingConstants = false;
/** Performs the {@code /} operator on the two values. */ public static double dividedBy(SoyValue operand0, SoyValue operand1) { // Note: Soy always performs floating-point division, even on two integers (like JavaScript). // Note that this *will* lose precision for longs. return operand0.numberValue() / operand1.numberValue(); }
/** Performs the {@code <=} operator on the two values. */ public static boolean lessThanOrEqual(SoyValue left, SoyValue right) { if (left instanceof SoyString && right instanceof SoyString) { return left.stringValue().compareTo(right.stringValue()) <= 0; } else if (left instanceof IntegerData && right instanceof IntegerData) { return left.longValue() <= right.longValue(); } else { return left.numberValue() <= right.numberValue(); } }
@Override public SoyValue applyForJava(SoyValue value, List<SoyValue> args) { int maxLen; try { maxLen = args.get(0).integerValue(); } catch (SoyDataException sde) { throw new IllegalArgumentException( "Could not parse first parameter of '|truncate' as integer (value was \"" + args.get(0).stringValue() + "\")."); } String str = value.coerceToString(); boolean doAddEllipsis; if (args.size() == 2) { try { doAddEllipsis = args.get(1).booleanValue(); } catch (SoyDataException sde) { throw new IllegalArgumentException( "Could not parse second parameter of '|truncate' as boolean."); } } else { doAddEllipsis = true; // default to true } return StringData.forValue(BasicDirectivesRuntime.truncate(str, maxLen, doAddEllipsis)); }
/** Rounds the given value to the closest integer. */ public static long round(SoyValue value) { if (value instanceof IntegerData) { return value.longValue(); } else { return Math.round(value.numberValue()); } }
/** * Gets the integer index out of a SoyValue key, or throws SoyDataException if the key is not an * integer. * * @param key The SoyValue key. * @return The index. */ protected final int getIntegerIndex(SoyValue key) { if (key instanceof StringData) { try { // TODO(gboyer): Remove this case as non-compliant code is fixed. However, since this works // in Javascript, it is particularly difficult to fix callers. (internal) b/11416037 return Integer.parseInt(key.stringValue()); } catch (IllegalArgumentException e) { throw new SoyDataException("\"" + key + "\" is not a valid list index (must be an int)"); } } else { return key.integerValue(); } }