GitHub - sebastienros/shortcodes: Shortcodes processor for .NET (original) (raw)
Basic Overview
Shortcodes processor for .NET with focus on performance and simplicity.
Features
- Parses and renders shortcodes.
- Supports async shortcode to execute database queries and async operations more efficiently under load.
- Named and positioned arguments.
Contents
Sample usage
Don't forget to include the using statement:
Predefined shortcodes
var processor = new ShortcodesProcessor(new NamedShortcodeProvider { ["hello"] = (args, content, ctx) => new ValueTask("Hello world!") });
Console.WriteLine(await processor.EvaluateAsync("This is an [hello]"));
Which results in
Named arguments
Arguments can contain any character, but need to be quoted either with '
or "
if they contain spaces. Strings can use standard string escape sequences like \u03A9
and \n
.
var processor = new ShortcodesProcessor(new NamedShortcodeProvider { ["bold"] = (args, content, ctx) => { var text = args.Named("text");
return new ValueTask<string>($"<b>{text}</b>");
}
});
Console.WriteLine(await processor.EvaluateAsync("[bold text='bold text' 1234]"));
Content arguments
Shortcodes using opening and closing tags can access their inner content.
var processor = new ShortcodesProcessor(new NamedShortcodeProvider { ["bold"] = (args, content, ctx) => { return new ValueTask($"{content}"); } });
Console.WriteLine(await processor.EvaluateAsync("[bold]bold text[/bold]"));
For single tags, the content is null
. It means that you can detect if a shortcode was used with a closing tag, even if the inner content is empty.
Positional arguments
If an argument doesn't have a name, an default index can be used.
var processor = new ShortcodesProcessor(new NamedShortcodeProvider { ["bold"] = (args, content, ctx) => { var text = args.NamedOrDefault("text");
return new ValueTask<string>($"<b>{text}</b>");
}
});
Console.WriteLine(await processor.EvaluateAsync("[bold 'bold text']"));
Named and positional arguments can be mixed together. Each time an argument doesn't have a name, the index is incremented.
var processor = new ShortcodesProcessor(new NamedShortcodeProvider { ["bold"] = (args, content, ctx) => { var text = args.At(0);
return new ValueTask<string>($"<b>{text}</b>");
}
});
Console.WriteLine(await processor.EvaluateAsync("[bold id='a' 'some text']"));
Escaping tags
In case you want to render a shortcode instead of evaluating it, you can double the opening and closing braces.
[[bold] some text to show [/bold]]
Will then be rendered as
[bold] some text to show [/bold]
And for single tags:
Will be rendered as
In case several braces are used, and they are balanced, a single one will be escaped.
Will be rendered as:
Not that unbalanced braces won't be escaped.
Will be rendered as
Context object
A Context object can be passed when evaluating a template. This object is shared across all shortcodes
A common usage is to pass custom data that might be used by some shortcodes, like the current HttpContext
if a template is running in a web application and needs to access the current request.
Another usage is to use it as a bag of values that can be shared across shortcodes.
// From a Startup.cs class
var processor = new ShortcodesProcessor(new NamedShortcodeProvider { ["username"] = (args, content, ctx) => { var httpContext = (HttpContext)ctx["HttpContext"];
return new ValueTask<string>(httpContext.User.Identity.Name);
}
});
app.Run((httpContext) => { var context = new Context(){ ["HttpContext"] = httpContext }; var result = await processor.EvaluateAsync("The current user is [username]", context); return context.Response.WriteAsync(result); });
The current user is admin