using NTDLS.Helpers; using System.Text; using TightWiki.Engine.Function; using TightWiki.Engine.Implementation.Utility; using TightWiki.Engine.Library; using TightWiki.Engine.Library.Interfaces; using static TightWiki.Engine.Function.FunctionPrototypeCollection; using static TightWiki.Engine.Library.Constants; namespace TightWiki.Engine.Implementation { /// /// Handled scope function calls. /// public class ScopeFunctionHandler : IScopeFunctionHandler { private static FunctionPrototypeCollection? _collection; public FunctionPrototypeCollection Prototypes { get { if (_collection == null) { _collection = new FunctionPrototypeCollection(WikiFunctionType.Scoped); #region Prototypes. _collection.Add("$$Code: {language(auto,wiki,cpp,lua,graphql,swift,r,yaml,kotlin,scss,shell,vbnet,json,objectivec,perl,diff,wasm,php,xml,bash,csharp,css,go,ini,javascript,less,makefile,markdown,plaintext,python,python-repl,ruby,rust,sql,typescript)}='auto'"); _collection.Add("$$Bullets: {type(unordered,ordered)}='unordered'"); _collection.Add("$$Order: {direction(ascending,descending)}='ascending'"); _collection.Add("$$Jumbotron:"); _collection.Add("$$Callout: {styleName(default,primary,secondary,success,info,warning,danger)}='default' | {titleText}=''"); _collection.Add("$$Background: {styleName(default,primary,secondary,light,dark,success,info,warning,danger,muted)}='default'"); _collection.Add("$$Foreground: {styleName(default,primary,secondary,light,dark,success,info,warning,danger,muted)}='default'"); _collection.Add("$$Alert: {styleName(default,primary,secondary,light,dark,success,info,warning,danger)}='default' | {titleText}=''"); _collection.Add("$$Card: {styleName(default,primary,secondary,light,dark,success,info,warning,danger)}='default' | {titleText}=''"); _collection.Add("$$Collapse: {linkText}='Show'"); _collection.Add("$$Table: {hasBorder}='true' | {isFirstRowHeader}='true'"); _collection.Add("$$StripedTable: {hasBorder}='true' | {isFirstRowHeader}='true'"); _collection.Add("$$DefineSnippet: [name]"); #endregion } return _collection; } } /// /// Called to handle function calls when proper prototypes are matched. /// /// Reference to the wiki state object /// The parsed function call and all its parameters and their values. /// The the text that the function is designed to affect. public HandlerResult Handle(ITightEngineState state, FunctionCall function, string? scopeBody = null) { scopeBody.EnsureNotNull($"The function '{function.Name}' scope body can not be null"); switch (function.Name.ToLower()) { //------------------------------------------------------------------------------------------------------------------------------ case "code": { var html = new StringBuilder(); string language = function.Parameters.Get("language"); if (string.IsNullOrEmpty(language) || language?.ToLower() == "auto") { html.Append($"
");
                            html.Append($"{scopeBody.Replace("\r\n", "\n").Replace("\n", SoftBreak)}
"); } else { html.Append($"
");
                            html.Append($"{scopeBody.Replace("\r\n", "\n").Replace("\n", SoftBreak)}
"); } return new HandlerResult(html.ToString()) { Instructions = [HandlerResultInstruction.DisallowNestedProcessing] }; } //------------------------------------------------------------------------------------------------------------------------------ case "stripedtable": case "table": { var html = new StringBuilder(); var hasBorder = function.Parameters.Get("hasBorder"); var isFirstRowHeader = function.Parameters.Get("isFirstRowHeader"); html.Append($""); var lines = scopeBody.Split(['\n'], StringSplitOptions.RemoveEmptyEntries).Select(o => o.Trim()).Where(o => o.Length > 0); int rowNumber = 0; foreach (var lineText in lines) { var columns = lineText.Split("||"); if (rowNumber == 0 && isFirstRowHeader) { html.Append($""); } else if (rowNumber == 1 && isFirstRowHeader || rowNumber == 0 && isFirstRowHeader == false) { html.Append($""); } html.Append($""); foreach (var columnText in columns) { if (rowNumber == 0 && isFirstRowHeader) { html.Append($""); } else { html.Append($""); } } if (rowNumber == 0 && isFirstRowHeader) { html.Append($""); } html.Append($""); rowNumber++; } html.Append($""); html.Append($"
{columnText}{columnText}
"); return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "bullets": { var html = new StringBuilder(); string type = function.Parameters.Get("type"); if (type == "unordered") { var lines = scopeBody.Split(['\n'], StringSplitOptions.RemoveEmptyEntries).Select(o => o.Trim()).Where(o => o.Length > 0); int currentLevel = 0; foreach (var line in lines) { int newIndent = 0; for (; newIndent < line.Length && line[newIndent] == '>'; newIndent++) { //Count how many '>' are at the start of the line. } newIndent++; if (newIndent < currentLevel) { for (; currentLevel != newIndent; currentLevel--) { html.Append($""); } } else if (newIndent > currentLevel) { for (; currentLevel != newIndent; currentLevel++) { html.Append($"
    "); } } html.Append($"
  • {line.Trim(['>'])}
  • "); } for (; currentLevel > 0; currentLevel--) { html.Append($"
"); } } else if (type == "ordered") { var lines = scopeBody.Split(['\n'], StringSplitOptions.RemoveEmptyEntries).Select(o => o.Trim()).Where(o => o.Length > 0); int currentLevel = 0; foreach (var line in lines) { int newIndent = 0; for (; newIndent < line.Length && line[newIndent] == '>'; newIndent++) { //Count how many '>' are at the start of the line. } newIndent++; if (newIndent < currentLevel) { for (; currentLevel != newIndent; currentLevel--) { html.Append($""); } } else if (newIndent > currentLevel) { for (; currentLevel != newIndent; currentLevel++) { html.Append($"
    "); } } html.Append($"
  1. {line.Trim(['>'])}
  2. "); } for (; currentLevel > 0; currentLevel--) { html.Append($"
"); } } return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "definesnippet": { var html = new StringBuilder(); string name = function.Parameters.Get("name"); if (!state.Snippets.TryAdd(name, scopeBody)) { state.Snippets[name] = scopeBody; } return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "alert": { var html = new StringBuilder(); string titleText = function.Parameters.Get("titleText"); string style = function.Parameters.Get("styleName").ToLower(); style = style == "default" ? "" : $"alert-{style}"; if (!string.IsNullOrEmpty(titleText)) scopeBody = $"

{titleText}

{scopeBody}"; html.Append($"
{scopeBody}
"); return new HandlerResult(html.ToString()); } case "order": { var html = new StringBuilder(); string direction = function.Parameters.Get("direction"); var lines = scopeBody.Split("\n").Select(o => o.Trim()).ToList(); if (direction == "ascending") { html.Append(string.Join("\r\n", lines.OrderBy(o => o))); } else { html.Append(string.Join("\r\n", lines.OrderByDescending(o => o))); } return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "jumbotron": { var html = new StringBuilder(); string titleText = function.Parameters.Get("titleText", ""); html.Append($"
"); if (!string.IsNullOrEmpty(titleText)) html.Append($"

{titleText}

"); html.Append($"

{scopeBody}

"); html.Append($"
"); return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "foreground": { var html = new StringBuilder(); var style = BGFGStyle.GetForegroundStyle(function.Parameters.Get("styleName", "default")).Swap(); html.Append($"

{scopeBody}

"); return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "background": { var html = new StringBuilder(); var style = BGFGStyle.GetBackgroundStyle(function.Parameters.Get("styleName", "default")); html.Append($"
{scopeBody}
"); return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "collapse": { var html = new StringBuilder(); string linkText = function.Parameters.Get("linktext"); string uid = "A" + Guid.NewGuid().ToString().Replace("-", ""); html.Append($"{linkText}"); html.Append($"
"); html.Append($"

{scopeBody}

"); return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "callout": { var html = new StringBuilder(); string titleText = function.Parameters.Get("titleText"); string style = function.Parameters.Get("styleName").ToLower(); style = style == "default" ? "" : style; html.Append($"
"); if (string.IsNullOrWhiteSpace(titleText) == false) html.Append($"

{titleText}

"); html.Append($"{scopeBody}"); html.Append($"
"); return new HandlerResult(html.ToString()); } //------------------------------------------------------------------------------------------------------------------------------ case "card": { var html = new StringBuilder(); string titleText = function.Parameters.Get("titleText"); var style = BGFGStyle.GetBackgroundStyle(function.Parameters.Get("styleName", "default")); html.Append($"
"); if (string.IsNullOrEmpty(titleText) == false) { html.Append($"
{titleText}
"); } html.Append("
"); html.Append($"

{scopeBody}

"); html.Append("
"); html.Append("
"); return new HandlerResult(html.ToString()); } } return new HandlerResult() { Instructions = [HandlerResultInstruction.Skip] }; } } }