in src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/MarkupHandler.java [201:277]
private void emitSingleFragment(String name, Interpolation interpolation, char quoteChar, PluginInvoke invoke) {
Expression valueExpression = expressionWrapper.transform(interpolation, null, ExpressionContext.ATTRIBUTE); //raw expression
String attrValue = symbolGenerator.next("attrValue"); //holds the raw attribute value
String attrContent = symbolGenerator.next("attrContent"); //holds the escaped attribute value
String isTrueVar = symbolGenerator.next("isTrueAttr"); // holds the comparison (attrValue == true)
String shouldDisplayAttr = symbolGenerator.next("shouldDisplayAttr");
MarkupContext markupContext = getAttributeMarkupContext(name);
boolean alreadyEscaped = false;
if (valueExpression.getRoot() instanceof RuntimeCall) {
RuntimeCall rc = (RuntimeCall) valueExpression.getRoot();
if (RuntimeCall.XSS.equals(rc.getFunctionName())) {
alreadyEscaped = true;
}
}
ExpressionNode node = valueExpression.getRoot();
stream.write(new VariableBinding.Start(attrValue, node)); //attrContent = <expr>
if (!alreadyEscaped) {
Expression contentExpression = valueExpression.withNode(new Identifier(attrValue));
stream.write(new VariableBinding.Start(attrContent, adjustContext(compilerContext, contentExpression, markupContext).getRoot()));
stream.write(
new VariableBinding.Start(
shouldDisplayAttr,
new BinaryOperation(
BinaryOperator.AND,
new BinaryOperation(
BinaryOperator.AND,
new BinaryOperation(BinaryOperator.NEQ, NullLiteral.INSTANCE, new Identifier(attrContent)),
new BinaryOperation(BinaryOperator.NEQ, StringConstant.EMPTY, new Identifier(attrContent))
),
new BinaryOperation(BinaryOperator.AND,
new BinaryOperation(BinaryOperator.NEQ, StringConstant.EMPTY, new Identifier(attrValue)),
new BinaryOperation(BinaryOperator.NEQ, BooleanConstant.FALSE, new Identifier(attrValue))
)
)
)
);
} else {
stream.write(
new VariableBinding.Start(
shouldDisplayAttr,
new BinaryOperation(
BinaryOperator.AND,
new BinaryOperation(BinaryOperator.NEQ, NullLiteral.INSTANCE, new Identifier(attrValue)),
new BinaryOperation(
BinaryOperator.AND,
new BinaryOperation(BinaryOperator.NEQ, StringConstant.EMPTY, new Identifier(attrValue)),
new BinaryOperation(BinaryOperator.NEQ, BooleanConstant.FALSE, new Identifier(attrValue))
)
)
)
);
}
stream.write(new Conditional.Start(shouldDisplayAttr, true)); // if (attrContent)
emitAttributeStart(name); //write("attrName");
invoke.beforeAttributeValue(stream, name, node);
stream.write(new VariableBinding.Start(isTrueVar, //isTrueAttr = (attrValue == true)
new BinaryOperation(BinaryOperator.EQ, BooleanConstant.TRUE, new Identifier(attrValue))));
stream.write(new Conditional.Start(isTrueVar, false)); //if (!isTrueAttr)
emitAttributeValueStart(quoteChar); // write("='");
if (!alreadyEscaped) {
stream.write(new OutputVariable(attrContent)); //write(attrContent)
} else {
stream.write(new OutputVariable(attrValue)); // write(attrValue)
}
emitAttributeEnd(quoteChar); //write("'");
stream.write(Conditional.END); //end if isTrueAttr
stream.write(VariableBinding.END); //end scope for isTrueAttr
invoke.afterAttributeValue(stream, name);
stream.write(Conditional.END); //end if attrContent
stream.write(VariableBinding.END); //end scope for attrContent
if (!alreadyEscaped) {
stream.write(VariableBinding.END);
}
stream.write(VariableBinding.END); //end scope for attrValue
}