-
Notifications
You must be signed in to change notification settings - Fork 168
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* issue #520: provide option to customize stock extensions * issue #520: only one customizer / hide implementation details * issue #520: JavaDoc & cleanups * issue #520: added documentation
- Loading branch information
pepperbob
authored
Dec 18, 2020
1 parent
4a21f3b
commit 4fc15f7
Showing
6 changed files
with
266 additions
and
40 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
docs/src/orchid/resources/wiki/guide/customize-defaults.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
--- | ||
--- | ||
|
||
Pebble comes with a rich set of built-in tags and filters that will help you render your templates into websites and other documents with ease. However, imagine a more specific use-case where the templates are not entirely under your control. | ||
|
||
In these cases it might be advised to consider stripping-down Pebbles' built-in functionality that may otherwise introduce security-concers regarding the integrity and stability of your application. | ||
|
||
### Opt-Out using ExtensionCustomizer | ||
|
||
The `ExtensionCustomizer` base class can be used to gain access to the default functionality before it is loaded into Pebbles template engine. Overwrite methods to get hold on provided default-functionality and modify whatever should be available for the template engine. | ||
|
||
The following example removes the `ForTokenParser`, i.e. the ability to parse `{% for %}{{ ... }}{% endfor %}` constructs: | ||
|
||
```java | ||
class ExampleOptOuts extends ExtensionCustomizer { | ||
|
||
public ExampleOptOuts(Extension ext) { | ||
super(ext); | ||
} | ||
|
||
@Override | ||
public List<TokenParser> getTokenParsers() { | ||
List<TokenParser> tokenParsers = Optional.ofNullable(super.getTokenParsers()) | ||
.map(ArrayList::new).orElseGet(ArrayList::new); | ||
|
||
tokenParsers.removeIf(x -> x instanceof ForTokenParser); | ||
return tokenParsers; | ||
} | ||
|
||
} | ||
``` | ||
|
||
The `ExtensionCustomizer` will be used to wrap any Pebble-extension which is provided by default. It can be registered in your setup code to create `PebbleEngine`: | ||
|
||
```java | ||
PebbleEngine engine = new PebbleEngine.Builder().registerCustomizer(ExampleOptOuts::new).build(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
pebble/src/main/java/com/mitchellbosecke/pebble/extension/ExtensionCustomizer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.mitchellbosecke.pebble.extension; | ||
|
||
import com.mitchellbosecke.pebble.attributes.AttributeResolver; | ||
import com.mitchellbosecke.pebble.operator.BinaryOperator; | ||
import com.mitchellbosecke.pebble.operator.UnaryOperator; | ||
import com.mitchellbosecke.pebble.tokenParser.TokenParser; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* Base class that allows implementing a customizer to modify Pebbles build-in extensions. | ||
* It is meant to provide a way to remove or replace functions, filters, tags, etc. to change | ||
* the standard behaviour. Use-cases can be down-stripping available functionality for security | ||
* reasons. | ||
* | ||
* Implementations of this class are meant to overwrite methods and access registered functionality | ||
* before it is loaded into the PebbleEngine by calling super. | ||
* | ||
* The ExentsionCustomizer can be registred via {@link com.mitchellbosecke.pebble.PebbleEngine.Builder#registerExtensionCustomizer} | ||
* and is applied for every non-user-provided extension. | ||
* | ||
*/ | ||
public abstract class ExtensionCustomizer implements Extension { | ||
|
||
private final Extension delegate; | ||
|
||
public ExtensionCustomizer(Extension delegate) { | ||
this.delegate = delegate; | ||
} | ||
|
||
@Override | ||
public Map<String, Filter> getFilters() { | ||
return delegate.getFilters(); | ||
} | ||
|
||
@Override | ||
public Map<String, Test> getTests() { | ||
return delegate.getTests(); | ||
} | ||
|
||
@Override | ||
public Map<String, Function> getFunctions() { | ||
return delegate.getFunctions(); | ||
} | ||
|
||
@Override | ||
public List<TokenParser> getTokenParsers() { | ||
return delegate.getTokenParsers(); | ||
} | ||
|
||
@Override | ||
public List<BinaryOperator> getBinaryOperators() { | ||
return delegate.getBinaryOperators(); | ||
} | ||
|
||
@Override | ||
public List<UnaryOperator> getUnaryOperators() { | ||
return delegate.getUnaryOperators(); | ||
} | ||
|
||
@Override | ||
public Map<String, Object> getGlobalVariables() { | ||
return delegate.getGlobalVariables(); | ||
} | ||
|
||
@Override | ||
public List<NodeVisitorFactory> getNodeVisitors() { | ||
return delegate.getNodeVisitors(); | ||
} | ||
|
||
@Override | ||
public List<AttributeResolver> getAttributeResolver() { | ||
return delegate.getAttributeResolver(); | ||
} | ||
|
||
} |
72 changes: 72 additions & 0 deletions
72
pebble/src/main/java/com/mitchellbosecke/pebble/extension/ExtensionRegistryFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package com.mitchellbosecke.pebble.extension; | ||
|
||
import com.mitchellbosecke.pebble.extension.core.AttributeResolverExtension; | ||
import com.mitchellbosecke.pebble.extension.core.CoreExtension; | ||
import com.mitchellbosecke.pebble.extension.escaper.EscaperExtension; | ||
import com.mitchellbosecke.pebble.extension.escaper.EscapingStrategy; | ||
import com.mitchellbosecke.pebble.extension.i18n.I18nExtension; | ||
|
||
import java.util.*; | ||
import java.util.function.Function; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
* Provides configuration methods and builds the {@link ExtensionRegistry}. Used only internally by | ||
* the {@link com.mitchellbosecke.pebble.PebbleEngine.Builder}. | ||
* | ||
*/ | ||
public class ExtensionRegistryFactory { | ||
|
||
private final List<Extension> userProvidedExtensions = new ArrayList<>(); | ||
|
||
private final EscaperExtension escaperExtension = new EscaperExtension(); | ||
|
||
private boolean allowOverrideCoreOperators = false; | ||
|
||
private Function<Extension, Extension> customizer = Function.identity(); | ||
|
||
public ExtensionRegistry buildExtensionRegistry() { | ||
ExtensionRegistry extensionRegistry = new ExtensionRegistry(); | ||
|
||
Stream.of(new CoreExtension(), this.escaperExtension, new I18nExtension()) | ||
.map(customizer::apply) | ||
.forEach(extensionRegistry::addExtension); | ||
|
||
for (Extension userProvidedExtension : this.userProvidedExtensions) { | ||
if (this.allowOverrideCoreOperators) { | ||
extensionRegistry.addOperatorOverridingExtension(userProvidedExtension); | ||
} else { | ||
extensionRegistry.addExtension(userProvidedExtension); | ||
} | ||
} | ||
|
||
extensionRegistry.addExtension(customizer.apply(new AttributeResolverExtension())); | ||
|
||
return extensionRegistry; | ||
} | ||
|
||
public void autoEscaping(boolean autoEscaping) { | ||
this.escaperExtension.setAutoEscaping(autoEscaping); | ||
} | ||
|
||
public void addEscapingStrategy(String name, EscapingStrategy strategy) { | ||
this.escaperExtension.addEscapingStrategy(name, strategy); | ||
} | ||
|
||
public void extension(Extension... extensions) { | ||
Collections.addAll(this.userProvidedExtensions, extensions); | ||
} | ||
|
||
public void allowOverrideCoreOperators(boolean allowOverrideCoreOperators) { | ||
this.allowOverrideCoreOperators = allowOverrideCoreOperators; | ||
} | ||
|
||
public void defaultEscapingStrategy(String strategy) { | ||
this.escaperExtension.setDefaultStrategy(strategy); | ||
} | ||
|
||
public void registerExtensionCustomizer(Function<Extension, ExtensionCustomizer> customizer) { | ||
this.customizer = customizer::apply; | ||
} | ||
|
||
} |
Oops, something went wrong.