Extending and custom functions | Scriban
- Home
- Docs
- Runtime API
- Extending
Extending TemplateContext
You may need to extend a TemplateContext to overrides some methods there, typically in cases you want:
- To hook into whenever a
ScriptNodeAST node is evaluated - To catch if a property/member is accessed and should not be null
- Provides a
IObjectAccessorfor non .NET, nonDictionary<string, object>in case you are looking to expose a specific object to the runtime that requires a specific access pattern. By overriding the methodGetMemberAccessorImplyou can override this aspect. - To override
ToString(span, object)method to provide customToStringfor specifics .NET objects. - ...etc.
ScriptObject advanced usages
It is sometimes required for a custom function to have access to the current TemplateContext or to the access to original location of the text code, where a particular expression is occurring (via a SourceSpan that gives a line, column and sourcefile )
Advanced custom functions
In the ScriptObject section we described how to easily import a custom function either by using a delegate or a pre-defined .NET static functions/properties.
In some cases, you also need to have access to the current TemplateContext and also, the current SourceSpan (original location position in the text template code).
By simply adding as a first parameter TemplateContext, and optionally as a second parameter, a SourceSpan a custom function can have access to the current evaluation context:
var scriptObject1 = new ScriptObject();
// Here, we can have access to the `TemplateContext`
scriptObject1.Import("contextAccess", new Func<TemplateContext, string>(templateContext => "Yes"));
Hyper custom functions - IScriptCustomFunction
Some custom functions can require deeper access to the internals for exposing a function. Scriban provides the interface IScriptCustomFunction for this matter. If an object inherits from this interface and is accessed another ScriptObject, it will call the method IScriptCustomFunction.Invoke.
namespace Scriban.Runtime
{
/// <summary>
/// Allows to create a custom function object.
/// </summary>
public interface IScriptCustomFunction
{
/// <summary>
/// Calls the custom function object.
/// </summary>
/// <param name="context">The template context</param>
/// <param name="callerContext">The script node originating this call</param>
/// <param name="parameters">The parameters of the call</param>
/// <param name="blockStatement">The current block statement this call is made</param>
/// <returns>The result of the call</returns>
object Invoke(TemplateContext context, ScriptNode callerContext, ScriptArray parameters, ScriptBlockStatement blockStatement);
}
}
As you can see, the IScriptCustomFunction gives you access to:
- The current
TemplateContextevaluating the currentTemplate - The AST node context from the
Templatethat is calling this custom functions, so you can precisely get information about the location of the parameters in the original source code...etc. - The parameters already evaluated
- The block statement (not yet used for custom functions - but used by the
wrapstatement)
The include expression is typically implemented via a IScriptCustomFunction. You can have a look at the details here