1 package de.juplo.thymeleaf;
4 import org.thymeleaf.context.ITemplateContext;
5 import org.thymeleaf.engine.AttributeName;
6 import org.thymeleaf.engine.EngineEventUtils;
7 import org.thymeleaf.exceptions.TemplateProcessingException;
8 import org.thymeleaf.model.IProcessableElementTag;
9 import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
10 import org.thymeleaf.processor.element.IElementTagStructureHandler;
11 import org.thymeleaf.standard.expression.FragmentExpression;
12 import org.thymeleaf.standard.expression.FragmentExpression.ExecutedFragmentExpression;
13 import org.thymeleaf.standard.expression.IStandardExpression;
14 import org.thymeleaf.standard.expression.IStandardExpressionParser;
15 import org.thymeleaf.standard.expression.NoOpToken;
16 import org.thymeleaf.standard.expression.StandardExpressionExecutionContext;
17 import org.thymeleaf.standard.expression.StandardExpressions;
18 import org.thymeleaf.templatemode.TemplateMode;
22 * Subsitutes the element, that is marked with this attribute-processor.
26 public abstract class AbstractSubstituteAttributeProcessor extends AbstractAttributeTagProcessor
28 public static final int ATTR_PRECEDENCE = 100;
30 private final String substituteName;
33 public AbstractSubstituteAttributeProcessor(String prefix, String attribute, String substitute)
35 super(TemplateMode.HTML, prefix, null, false, attribute, true, ATTR_PRECEDENCE, true);
36 this.substituteName = substitute;
41 protected void doProcess(
42 final ITemplateContext context,
43 final IProcessableElementTag element,
44 final AttributeName name,
45 final String attribute,
46 final IElementTagStructureHandler handler
49 if (attribute == null)
53 final IStandardExpression expression =
54 EngineEventUtils.computeAttributeExpression(
61 if (expression != null && expression instanceof FragmentExpression)
63 final ExecutedFragmentExpression executedFragmentExpression =
64 FragmentExpression.createExecutedFragmentExpression(
66 (FragmentExpression) expression,
67 StandardExpressionExecutionContext.NORMAL
70 FragmentExpression.resolveExecutedFragmentExpression(
72 executedFragmentExpression,
78 result = expression.execute(context);
81 handler.removeAttribute(name);
83 // If the result of this expression is NO-OP, there is nothing to execute
84 if (result == NoOpToken.VALUE)
89 // We must not clone the processors, because we remove attributes
90 Element substituteElement =
91 element.cloneElementNodeWithNewName(element, substituteName, false);
92 // Remove attributes, that are not allowed for <span> or <strong>
93 substituteElement.removeAttribute("charset");
94 substituteElement.removeAttribute("th:charset");
95 substituteElement.removeAttribute("coords");
96 substituteElement.removeAttribute("href");
97 substituteElement.removeAttribute("th:href");
98 substituteElement.removeAttribute("hreflang");
99 substituteElement.removeAttribute("th:hreflang");
100 substituteElement.removeAttribute("media");
101 substituteElement.removeAttribute("th:media");
102 substituteElement.removeAttribute("name");
103 substituteElement.removeAttribute("th:name");
104 substituteElement.removeAttribute("rel");
105 substituteElement.removeAttribute("th:rel");
106 substituteElement.removeAttribute("ref");
107 substituteElement.removeAttribute("th:ref");
108 substituteElement.removeAttribute("shape");
109 substituteElement.removeAttribute("target");
110 substituteElement.removeAttribute("th:target");
111 substituteElement.removeAttribute("type");
112 substituteElement.removeAttribute("th:type");
113 // Also remove the title-attribute, because the mouse-over is confusing
114 substituteElement.removeAttribute("title");
115 substituteElement.removeAttribute("th:title");
116 // Replace the element
117 element.clearChildren();
118 element.addChild(substituteElement);
119 element.getParent().extractChild(element);
121 return ProcessorResult.OK;