Script Plugins

Similar to using Plugins in ServiceStack to easily add functionality to a ServiceStack AppHost, you can encapsulate a suite of functionality that can be easily added to extend a ScriptContext with related functionality, e.g: You can add Markdown functionality to your scripts with:

var context = new ScriptContext {
    Plugins = { 
        new MarkdownScriptPlugin { 
            RegisterPageFormat = false
        } 
    } 
}.Init();

Which will register Markdown filter transformers, script method and script block with our ScriptContext:

public class MarkdownScriptPlugin : IScriptPlugin
{
    public bool RegisterPageFormat { get; set; } = true;

    public void Register(ScriptContext context)
    {
        if (RegisterPageFormat)
            context.PageFormats.Add(new MarkdownPageFormat());
        
        context.FilterTransformers["markdown"] = MarkdownPageFormat.TransformToHtml;
        
        context.ScriptMethods.Add(new MarkdownScriptMethods());

        context.ScriptBlocks.Add(new MarkdownScriptBlock());
    }
}

Creating Plugins

Plugin are simply classes that implement IScriptPlugin interface and its Register() method to extend the ScriptContext with additional functionality we want to make available:

public interface IScriptPlugin
{
    void Register(ScriptContext context);
}

Plugins can implement the interfaces below if they need to run custom logic before and after plugins are registered:

// Run before plugins are loaded:
public interface IScriptPluginBefore
{
    void BeforePluginsLoaded(ScriptContext context);
}

// Run after plugins are loaded:
public interface IScriptPluginAfter
{
    void AfterPluginsLoaded(ScriptContext context);
}

Pre-registered Plugins in ScriptContext

Pre-registered plugins are useful when you want to easily remove a pre-registered suite of functionality, e.g:

var context = new ScriptContext {
        //...
    }
    .RemovePlugins(x => x is DefaultScriptBlocks) // Remove default blocks
    .RemovePlugins(x => x is HtmlScriptBlocks)    // Remove all html blocks
    .Init();

DefaultScriptBlocks

The Default Script Blocks contain all the statement functionality in #Script which includes:

public class DefaultScriptBlocks : IScriptPlugin
{
    public void Register(ScriptContext context)
    {
        context.ScriptBlocks.AddRange(new ScriptBlock[] {
            new IfScriptBlock(),
            new EachScriptBlock(),
            new RawScriptBlock(),
            new CaptureScriptBlock(), 
            new PartialScriptBlock(),
            new WithScriptBlock(),
            new NoopScriptBlock(),
            new KeyValuesScriptBlock(),
            new CsvScriptBlock(),
            new FunctionScriptBlock(), 
            new WhileScriptBlock(),
        });
    }
}

HtmlScriptBlocks

The purpose of the HTML Script Blocks is to pack a suite of generically useful functionality commonly used when generating html. All html blocks inherit the same functionality with blocks registered for the most popular HTML elements, currently:

public class HtmlScriptBlocks : IScriptPlugin
{
    /// <summary>
    /// Usages: {{#ul {each:items, class:'nav'} }} <li>{{it}}</li> {{/ul}}
    /// </summary>
    
    public void Register(ScriptContext context)
    {
        context.ScriptBlocks.AddRange(new ScriptBlock[] {
            new ScriptUlBlock(),
            new ScriptOlBlock(),
            new ScriptLiBlock(),
            new ScriptDivBlock(),
            new ScriptPBlock(), 
            new ScriptFormBlock(), 
            new ScriptInputBlock(), 
            new ScriptSelectBlock(), 
            new ScriptOptionBlock(),
            new ScriptTextAreaBlock(), 
            new ScriptButtonBlock(), 
            new ScriptTableBlock(),
            new ScriptTrBlock(),
            new ScriptTdBlock(),
            new ScriptTHeadBlock(),
            new ScriptTBodyBlock(),
            new ScriptTFootBlock(),
            new ScriptDlBlock(), 
            new ScriptDtBlock(), 
            new ScriptDdBlock(), 
            new ScriptSpanBlock(),
            new ScriptABlock(),
            new ScriptImgBlock(), 
            new ScriptEmBlock(), 
            new ScriptBBlock(), 
            new ScriptIBlock(), 
            new ScriptStrongBlock(), 
            new ScriptScriptBlock(),
            new ScriptStyleBlock(), 
            new ScriptLinkBlock(), 
            new ScriptMetaBlock(), 
        });
    }
}

Pre-registered Plugins in SharpPagesFeature

The SharpPagesFeature in ServiceStack.dll has access to more dependencies than ScriptContext and is able to pre-register more functionality by default including:

ServiceStackScriptBlocks

Containing the {{#minifyjs}}{{/minifyjs}}, {{#minifycss}}{{/minifycss}} and {{#minifyhtml}}{{/minifyhtml}} for minifying its contents:

public class ServiceStackScriptBlocks : IScriptPlugin
{
    public void Register(ScriptContext context)
    {
        context.ScriptBlocks.AddRange(new ScriptBlock[] {
            new MinifyJsScriptBlock(), 
            new MinifyCssScriptBlock(), 
            new MinifyHtmlScriptBlock(), 
            new SvgScriptBlock(), 
        });
    }
}

MarkdownScriptPlugin

Adds Markdown supports to #Script Pages by default:

public class MarkdownScriptPlugin : IScriptPlugin
{
    public bool RegisterPageFormat { get; set; } = true;

    public void Register(ScriptContext context)
    {
        if (RegisterPageFormat)
            context.PageFormats.Add(new MarkdownPageFormat());
        
        context.FilterTransformers["markdown"] = MarkdownPageFormat.TransformToHtml;
        
        context.ScriptMethods.Add(new MarkdownScriptMethods());

        context.ScriptBlocks.Add(new MarkdownScriptBlock());
    }
}

Added using:

Plugins.Add(new MarkdownScriptPlugin { RegisterPageFormat = false });

Available Plugins

List of available plugins that's not pre-registered anywhere include:

ProtectedScriptBlocks

public class ProtectedScriptBlocks : IScriptPlugin
{
    public void Register(ScriptContext context)
    {
        context.ScriptBlocks.AddRange(new ScriptBlock[] {
            new EvalScriptBlock(), // evalScript has same functionality and is registered by default 
        });
    }
}

Although generally not required as evalTemplate script method registered by default has equivalent functionality.

GitHubPlugin

ServiceStack's available GitHub integration can be used in your #Script by adding GitHubPlugin to your ScriptContext or SharpPagesFeature:

new ScriptContext {
    Plugins = { new GitHubPlugin() },
}.Init();

This is enabled by default in the web and app dotnet tools so they can be used in #Script .ss scripts.

Checkout GitHubScripts.cs for the full API available. Here's GitHub's Gist API example of creating gists in #Script:

githubGateway('GITHUB_GIST_TOKEN'.envVariable()) |> to => gateway

{{ gateway.githubCreateGist('Hello World Examples', {
     'hello_world_ruby.txt':   'Run `ruby hello_world.rb` to print Hello World',
     'hello_world_python.txt': 'Run `python hello_world.py` to print Hello World',
   })
   |> to => newGist }}

{ ...newGist, Files: null, Owner: null } |> textDump({ caption: 'new gist' })

View Gist files and metadata example:

gateway.githubGist(gistId) |> to => gist

{ ...gist, Files: null, Owner: null } |> textDump({ caption: 'gist' })

`#### Gist Files`
#each file in gist.Files.Keys
    gist.Files[file] |> textDump({ caption: file })
/each

Which renders the following GitHub Flavored Markdown output:

gist
Node Id MDQ6R2lzdDRjNWQ5NWVjNGIyNTk0YjRjZGQyMzg5ODdmZTdhMTVh
Git Pull Url https://gist.github.com/4c5d95ec4b2594b4cdd238987fe7a15a.git
Git Push Url https://gist.github.com/4c5d95ec4b2594b4cdd238987fe7a15a.git
Forks Url https://api.github.com/gists/4c5d95ec4b2594b4cdd238987fe7a15a/forks
Commits Url https://api.github.com/gists/4c5d95ec4b2594b4cdd238987fe7a15a/commits
Comments 0
Comments Url https://api.github.com/gists/4c5d95ec4b2594b4cdd238987fe7a15a/comments
Truncated False
Owner
Id 4c5d95ec4b2594b4cdd238987fe7a15a
Url https://api.github.com/gists/4c5d95ec4b2594b4cdd238987fe7a15a
Html Url https://gist.github.com/4c5d95ec4b2594b4cdd238987fe7a15a
Files
Public True
Created at 2019-06-15
Updated At 2019-06-15
Description Hello World Examples
User Id

Gist Files

hello_world_python.txt
Filename hello_world_python.txt
Type text/plain
Language Text
Raw Url https://gist.githubusercontent.com/gistlyn/.../hello_world_python.txt
Size 48
Truncated False
Content Run python hello_world.py to print Hello World
hello_world_ruby.txt
Filename hello_world_ruby.txt
Type text/plain
Language Text
Raw Url https://gist.githubusercontent.com/gistlyn/.../hello_world_ruby.txt
Size 46
Truncated False
Content Run ruby hello_world.rb to print Hello World

made with by ServiceStack