package de.juplo.thymeleaf;
-import org.thymeleaf.Arguments;
-import org.thymeleaf.Configuration;
-import org.thymeleaf.dom.Element;
-import org.thymeleaf.processor.ProcessorResult;
-import org.thymeleaf.processor.attr.AbstractAttrProcessor;
-import org.thymeleaf.standard.expression.IStandardExpression;
-import org.thymeleaf.standard.expression.IStandardExpressionParser;
-import org.thymeleaf.standard.expression.StandardExpressions;
+import java.util.HashMap;
+import java.util.Map;
+import org.thymeleaf.context.ITemplateContext;
+import org.thymeleaf.engine.AttributeName;
+import org.thymeleaf.engine.EngineEventUtils;
+import org.thymeleaf.model.IAttribute;
+import org.thymeleaf.model.ICloseElementTag;
+import org.thymeleaf.model.IModel;
+import org.thymeleaf.model.IModelFactory;
+import org.thymeleaf.model.IProcessableElementTag;
+import org.thymeleaf.model.ITemplateEvent;
+import org.thymeleaf.processor.element.AbstractAttributeModelProcessor;
+import org.thymeleaf.processor.element.IElementModelStructureHandler;
+import org.thymeleaf.templatemode.TemplateMode;
/**
*
* @author kai
*/
-public abstract class AbstractSubstituteAttrProcessor extends AbstractAttrProcessor
+public abstract class AbstractSubstituteAttrProcessor
+ extends
+ AbstractAttributeModelProcessor
{
public static final int ATTR_PRECEDENCE = 100;
+
+ private final String attributeName;
private final String substituteName;
- public AbstractSubstituteAttrProcessor(String attribute, String substitute)
+ public AbstractSubstituteAttrProcessor(
+ final String prefix,
+ final String attribute,
+ final String substitute
+ )
{
- super(attribute);
+ super(
+ TemplateMode.HTML,
+ prefix,
+ null,
+ false,
+ attribute,
+ true,
+ ATTR_PRECEDENCE,
+ false
+ );
+ this.attributeName = attribute;
this.substituteName = substitute;
}
@Override
- protected final ProcessorResult processAttribute(
- Arguments arguments,
- Element element,
- String name
+ protected void doProcess(
+ final ITemplateContext context,
+ final IModel model,
+ final AttributeName attributeName,
+ final String attributeValue,
+ final IElementModelStructureHandler handler
)
{
- Configuration configuration = arguments.getConfiguration();
- IStandardExpressionParser parser =
- StandardExpressions.getExpressionParser(configuration);
- String value = element.getAttributeValue(name);
- IStandardExpression expression =
- parser.parseExpression(configuration, arguments, value);
- element.removeAttribute(name);
- if ((Boolean)expression.execute(configuration, arguments))
+ final IProcessableElementTag element = (IProcessableElementTag) model.get(0);
+ final Object result =
+ EngineEventUtils.computeAttributeExpression(
+ context,
+ element,
+ attributeName,
+ attributeValue
+ )
+ .execute(context);
+
+ if (result == null || !(result instanceof Boolean))
{
- // We must not clone the processors, because we remove attributes
- Element substituteElement =
- element.cloneElementNodeWithNewName(element, substituteName, false);
- // Remove attributes, that are not allowed for <span> or <strong>
- substituteElement.removeAttribute("charset");
- substituteElement.removeAttribute("th:charset");
- substituteElement.removeAttribute("coords");
- substituteElement.removeAttribute("href");
- substituteElement.removeAttribute("th:href");
- substituteElement.removeAttribute("hreflang");
- substituteElement.removeAttribute("th:hreflang");
- substituteElement.removeAttribute("media");
- substituteElement.removeAttribute("th:media");
- substituteElement.removeAttribute("name");
- substituteElement.removeAttribute("th:name");
- substituteElement.removeAttribute("rel");
- substituteElement.removeAttribute("th:rel");
- substituteElement.removeAttribute("ref");
- substituteElement.removeAttribute("th:ref");
- substituteElement.removeAttribute("shape");
- substituteElement.removeAttribute("target");
- substituteElement.removeAttribute("th:target");
- substituteElement.removeAttribute("type");
- substituteElement.removeAttribute("th:type");
- // Also remove the title-attribute, because the mouse-over is confusing
- substituteElement.removeAttribute("title");
- substituteElement.removeAttribute("th:title");
- // Replace the element
- element.clearChildren();
- element.addChild(substituteElement);
- element.getParent().extractChild(element);
+ return;
}
- return ProcessorResult.OK;
- }
- @Override
- public final int getPrecedence()
- {
- return ATTR_PRECEDENCE;
+
+ IModelFactory factory = context.getModelFactory();
+
+ if ((Boolean)result)
+ {
+ Map<String, String> attributes = new HashMap<>();
+
+ for (IAttribute attribute : element.getAllAttributes())
+ {
+ String name =
+ attribute
+ .getAttributeDefinition()
+ .getAttributeName()
+ .getAttributeName()
+ .toLowerCase();
+ switch (name)
+ {
+ case "charset":
+ case "coords":
+ case "href":
+ case "hreflang":
+ case "media":
+ case "name":
+ case "rel":
+ case "ref":
+ case "shape":
+ case "target":
+ case "type":
+ // Also remove the title-attribute, because the mouse-over is confusing
+ case "title":
+ break;
+ default:
+ if (name.equals(this.attributeName))
+ continue;
+ attributes.put(attribute.getAttributeCompleteName(), attribute.getValue());
+ }
+ }
+
+ ITemplateEvent tag;
+ tag = factory.createOpenElementTag(substituteName, attributes, null, false);
+ model.replace(0, tag);
+ for (int i = model.size(); i > 0; --i)
+ {
+ tag = model.get(i);
+ if (!(tag instanceof ICloseElementTag))
+ continue;
+ ICloseElementTag close = (ICloseElementTag)tag;
+ if (close.isUnmatched())
+ continue;
+ if (close.getElementCompleteName().equals(element.getElementCompleteName()))
+ {
+ model.replace(i, factory.createCloseElementTag(substituteName, close.isSynthetic(), close.isUnmatched()));
+ break;
+ }
+ }
+ }
+ else
+ model.replace(0, factory.removeAttribute(element, attributeName));
}
}
import java.util.HashSet;
+import java.util.Locale;
import java.util.Set;
-import org.thymeleaf.dialect.AbstractDialect;
+import org.springframework.context.MessageSource;
+import org.thymeleaf.dialect.AbstractProcessorDialect;
import org.thymeleaf.processor.IProcessor;
* A collection of usefull tools.
* @author Kai Moritz
*/
-public class JuploDialect extends AbstractDialect
+public class JuploDialect extends AbstractProcessorDialect
{
+ public static final String DIALECT_NAME = "juplo-Dialect";
public static final String DIALECT_PREFIX = "juplo";
+ public static final int DIALECT_PRECEDENCE = 200;
- public JuploDialect()
- {
- super();
- }
+ final MessageSource messageSource;
+ final Locale defaultLocale;
- @Override
- public String getPrefix()
+ public JuploDialect(
+ final MessageSource messageSource,
+ final Locale defaultLocale
+ )
{
- return DIALECT_PREFIX;
+ super(DIALECT_NAME, DIALECT_PREFIX, DIALECT_PRECEDENCE);
+ this.messageSource = messageSource;
+ this.defaultLocale = defaultLocale;
}
+
@Override
- public Set<IProcessor> getProcessors()
+ public Set<IProcessor> getProcessors(String prefix)
{
final Set<IProcessor> processors = new HashSet<>();
- processors.add(new ActiveAttrProcessor());
- processors.add(new InactiveAttrProcessor());
+ processors.add(new ActiveAttributeProcessor(prefix));
+ processors.add(new InactiveAttributeProcessor(prefix));
processors.add(new ImportVariablesAttrProcessor());
return processors;
}