private MarkdownPage ParsePage(string fileName) { string html = CommonMark.CommonMarkConverter.Convert(File.ReadAllText(fileName)); HtmlTree tree = new HtmlTree(new TextStream(html)); tree.Build(); ElementNode firstChild = tree.RootNode.Children[0]; ElementNode prop = firstChild.Children[0]; MarkdownPage page = new MarkdownPage(); page.Title = AttrValue(prop, "pageTitle", Path.GetFileNameWithoutExtension(fileName)); page.Description = AttrValue(prop, "description", page.Title); page.Content = html.Substring(firstChild.End, tree.RootNode.Length - firstChild.End).Trim(); page.Keywords = AttrValue(prop, "keywords", page.Title); page.Slug = AttrValue(prop, "slug", page.Title.ToLowerInvariant()); page.DateModified = File.GetLastWriteTime(fileName); page.FileName = fileName.Replace(BaseDirectory, string.Empty).Replace("\\", "/"); page.ShowInMenu = Path.GetFileName(fileName).StartsWith("_") ? false : true; if (prop.GetAttribute("order") != null) page.Order = int.Parse(prop.GetAttribute("order").Value); else page.Order = 1000 + page.Title[0]; return page; }
private MarkdownPage RecursiveFindChildren(string directory, MarkdownPage parent) { string index = Path.Combine(directory, _index); MarkdownPage newParent = ParsePage(index); ValidatePage(newParent); newParent.Parent = parent; foreach (string file in Directory.EnumerateFiles(directory, "*.md").Where(f => Path.GetFileName(f) != _index)) { MarkdownPage child = ParsePage(file); child.Parent = newParent; ValidatePage(child); newParent.Children.Add(child); } foreach (string childDir in GetChildDirectories(directory)) { RecursiveFindChildren(childDir, newParent); } if (parent != null) { parent.Children.Add(newParent); parent.Children.Sort(new PageComparer()); } newParent.Children.Sort(new PageComparer()); return newParent; }
private void Prepare(MarkdownPage markdownPage) { var rawMethodExpr = methodExpr.Replace("Html.", ""); if (rawMethodExpr == "Partial") { this.DependentPageName = this.Condition.ExtractContents("\"", "\""); } this.WriteRawHtml = rawMethodExpr == "Raw"; var parts = methodExpr.Split('.'); if (parts.Length > 2) throw new ArgumentException("Unable to resolve method: " + methodExpr); var usesBaseType = parts.Length == 1; var typePropertyName = parts[0]; var methodName = usesBaseType ? parts[0] : parts[1]; Type type = null; if (typePropertyName == "Html") { type = markdownPage.ExecutionContext.BaseType.HasGenericType() ? typeof(HtmlHelper<>) : typeof(HtmlHelper); } if (type == null) { type = usesBaseType ? markdownPage.ExecutionContext.BaseType : markdownPage.Markdown.MarkdownGlobalHelpers.TryGetValue(typePropertyName, out type) ? type : null; } if (type == null) throw new InvalidDataException(string.Format( "Unable to resolve type '{0}'. Check type exists in Config.MarkdownBaseType or Page.Markdown.MarkdownGlobalHelpers", typePropertyName)); var mi = methodName == "Partial" ? type.GetMethods(BindingFlags.Public | BindingFlags.Instance) .FirstOrDefault(m => m.GetParameters().Length == 2 && m.Name == methodName) : type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance); if (mi == null) { mi = HtmlHelper.GetMethod(methodName); if (mi == null) throw new ArgumentException("Unable to resolve method '" + methodExpr + "' on type " + type.Name); } base.ReturnType = mi.ReturnType; var isMemberExpr = Condition.IndexOf('(') != -1; if (!isMemberExpr || this.WriteRawHtml) { base.Condition = methodExpr + "(" + Condition + ")"; } }
public void Can_inherit_from_CustomViewPage_using_inherits_directive() { var template = @"@inherits ServiceStack.ServiceHost.Tests.Formats.TemplateTests+CustomMarkdownViewBase<ServiceStack.ServiceHost.Tests.Formats.TemplateTests+Person> # Generic View Page ## Form fields @Html.LabelFor(m => m.FirstName) @Html.TextBoxFor(m => m.FirstName) ## Person Table @Table(Model) "; var expectedHtml = @" <h1>Generic View Page</h1> <h2>Form fields</h2> <label for=""FirstName"">FirstName</label> <input name=""FirstName"" type=""text"" value=""Demis"" /> <h2>Person Table</h2> <table><caption>Demis's Links</caption><thead><tr><th>Name</th><th>Link</th></tr></thead> <tbody> <tr><td>ServiceStack</td><td>http://www.servicestack.net</td></tr><tr><td>AjaxStack</td><td>http://www.ajaxstack.com</td></tr></tbody> </table> ".Replace("\r\n", "\n"); var dynamicPage = new MarkdownPage(markdownFormat, "/path/to/tpl", "DynamicModelTpl", template); dynamicPage.Prepare(); var templateOutput = dynamicPage.RenderToHtml(templateArgs); templateOutput = templateOutput.Replace("\r\n", "\n"); Assert.That(dynamicPage.ExecutionContext.BaseType, Is.EqualTo(typeof(CustomMarkdownViewBase <>))); Console.WriteLine(templateOutput); Assert.That(templateOutput, Is.EqualTo(expectedHtml)); }
private string RenderInTemplateIfAny(MarkdownPage markdownPage, Dictionary <string, object> scopeArgs, string pageHtml) { MarkdownTemplate markdownTemplate = null; var directiveTemplatePath = markdownPage.DirectiveTemplatePath; if (directiveTemplatePath != null) { if (!PageTemplates.TryGetValue(directiveTemplatePath, out markdownTemplate)) { if (!File.Exists(directiveTemplatePath)) { throw new FileNotFoundException("Could not find template: " + directiveTemplatePath); } var templateContents = File.ReadAllText(directiveTemplatePath); markdownTemplate = AddTemplate(directiveTemplatePath, templateContents); } } if (markdownTemplate == null) { var templatePath = markdownPage.TemplatePath; if (templatePath == null) { return(pageHtml); } markdownTemplate = PageTemplates[templatePath]; } if (scopeArgs != null) { scopeArgs[MarkdownTemplate.BodyPlaceHolder] = pageHtml; } var htmlPage = markdownTemplate.RenderToString(scopeArgs); return(htmlPage); }
public string Parse <TModel>(string markdownTemplate, TModel model, bool isHtml = true) { if (string.IsNullOrWhiteSpace(markdownTemplate)) { return(string.Empty); } var file = Path.GetTempFileName(); lock (SyncLock) { File.WriteAllText(file, markdownTemplate); } var fi = new FileInfo(file); if (fi.Length == 0) { fi.Delete(); return(string.Empty); } var mdFormat = new MarkdownFormat(); var mdPage = new MarkdownPage(mdFormat, file, "_markdown_", markdownTemplate); mdFormat.AddPage(mdPage); // attach view model var scopeArgs = new Dictionary <string, object> { { MarkdownPage.ModelName, model } }; var result = mdFormat.RenderDynamicPage(mdPage, scopeArgs, isHtml, false); // clean up temp file fi.Delete(); return(result); }
public void AddPage(MarkdownPage page) { try { page.Prepare(); switch (page.PageType) { case MarkdownPageType.ViewPage: ViewPages.Add(page.Name, page); break; case MarkdownPageType.SharedViewPage: ViewSharedPages.Add(page.Name, page); break; case MarkdownPageType.ContentPage: ContentPages.Add(page.FilePath.WithoutExtension(), page); break; } } catch (Exception ex) { Log.Error("AddViewPage() page.Prepare(): " + ex.Message, ex); } var templatePath = page.TemplatePath; if (page.TemplatePath == null) { return; } if (PageTemplates.ContainsKey(templatePath)) { return; } AddTemplate(templatePath, File.ReadAllText(templatePath)); }
public void Does_transform_escaped_html_start_tags() { var markdownText = @"#### Showing Results 1 - 5 ^<div id=""searchresults""> ### Markdown > [About Docs](http://path.com/to/about) ^</div> Text".NormalizeNewLines(); var expectedHtml = @"<h4>Showing Results 1 - 5</h4> <div id=""searchresults""> <h3>Markdown > <a href=""http://path.com/to/about"">About Docs</a></h3> </div> <p>Text</p> ".NormalizeNewLines(); var textBlock = new TextBlock(""); var page = new MarkdownPage { Markdown = new MarkdownFormat() }; textBlock.DoFirstRun(new PageContext(page, null, true)); var html = textBlock.TransformHtml(markdownText); Console.WriteLine(html); Assert.That(html, Is.EqualTo(expectedHtml)); }
public void Can_Render_MarkdownPage_with_unmatching_escaped_braces() { var template = @"# Dynamic If Markdown Template Hello @Model.FirstName, { -- unmatched, leave unescaped outside statement { -- inside matching braces, outside statement -- } @if (Model.LastName == ""Bellot"") { * @Model.LastName {{ -- inside matching braces, escape inside statement -- }} {{ -- unmatched } ### heading 3"; var expectedHtml = @"<h1>Dynamic If Markdown Template</h1> <p>Hello Demis, { -- unmatched, leave unescaped outside statement</p> <p>{ -- inside matching braces, outside statement -- }</p> <ul> <li>Bellot</li> </ul> <p>{ -- inside matching braces, escape inside statement -- }</p> <p>{ -- unmatched</p> <h3>heading 3</h3> ".NormalizeNewLines(); var dynamicPage = new MarkdownPage(markdownFormat, "/path/to/tpl", "DynamicIfTpl", template); dynamicPage.Compile(); var templateOutput = dynamicPage.RenderToHtml(templateArgs); Console.WriteLine(templateOutput); Assert.That(templateOutput, Is.EqualTo(expectedHtml)); }
public void Can_Render_MarkdownPage_with_comments() { var template = @"# Dynamic If Markdown Template Hello @Model.FirstName, @if (Model.FirstName == ""Bellot"") { * @Model.FirstName } @* @if (Model.LastName == ""Bellot"") { * @Model.LastName } *@ @* Plain text in a comment *@ ### heading 3"; var expectedHtml = @"<h1>Dynamic If Markdown Template</h1> <p>Hello Demis,</p> <h3>heading 3</h3> ".Replace("\r\n", "\n"); var dynamicPage = new MarkdownPage(markdownFormat, "/path/to/tpl", "DynamicIfTpl", template); dynamicPage.Prepare(); var templateOutput = dynamicPage.RenderToHtml(templateArgs); Console.WriteLine(templateOutput); Assert.That(templateOutput, Is.EqualTo(expectedHtml)); }
public void Transform(MarkdownPage input) { int id = 0; input.Contents = CheckedReplacer.Replace(input.Contents, (m) => { var html = ""; switch (m.Groups[1].Value) { case "x": case "X": { html = CheckedCheckbox; break; } case " ": { html = UncheckedCheckbox; break; } default: throw new NotImplementedException(); } html = String.Format(html, id++); return html; }); }
public void Can_Render_page_to_Markdown_only() { var headerTemplate = @"## Header Links! - [Google](http://google.com) - [Bing](http://bing.com) "; var template = @"## Welcome to Razor! @Html.Partial(""HeaderLinks"", Model) Hello @Upper(Model.LastName), @Model.FirstName ### Breadcrumbs @Combine("" / "", Model.FirstName, Model.LastName) ### Menus @foreach (var link in Model.Links) { - @link.Name - @link.Href @foreach (var label in link.Labels) { - @label } }"; var expectedHtml = @"## Welcome to Razor! ## Header Links! - [Google](http://google.com) - [Bing](http://bing.com) Hello BELLOT, Demis ### Breadcrumbs Demis / Bellot ### Menus - ServiceStack - http://www.servicestack.net - REST - JSON - XML - AjaxStack - http://www.ajaxstack.com - HTML5 - AJAX - SPA ".Replace("\r\n", "\n"); markdownFormat.RegisterMarkdownPage(new MarkdownPage(markdownFormat, "/path/to/page", "HeaderLinks", headerTemplate)); var dynamicPage = new MarkdownPage(markdownFormat, "/path/to/tpl", "DynamicModelTpl", template); dynamicPage.Prepare(); var templateOutput = dynamicPage.RenderToMarkdown(templateArgs); templateOutput = templateOutput.Replace("\r\n", "\n"); Assert.That(dynamicPage.ExecutionContext.BaseType, Is.EqualTo(typeof(MarkdownViewBase))); Console.WriteLine(templateOutput); Assert.That(templateOutput, Is.EqualTo(expectedHtml)); }
public void Can_Render_Markdown_with_StaticMethods() { var headerTemplate = @"## Header Links! - [Google](http://google.com) - [Bing](http://bing.com)"; var template = @"## Welcome to Razor! @Html.Partial(""HeaderLinks"", Model) Hello @Upper(Model.LastName), @Model.FirstName ### Breadcrumbs @Combine("" / "", Model.FirstName, Model.LastName) ### Menus @foreach (var link in Model.Links) { - @link.Name - @link.Href @foreach (var label in link.Labels) { - @label } } ### HTML Table @Table(Model) "; var expectedHtml = @"<h2>Welcome to Razor!</h2> <h2>Header Links!</h2> <ul> <li><a href=""http://google.com"">Google</a></li> <li><a href=""http://bing.com"">Bing</a></li> </ul> <p>Hello BELLOT, Demis</p> <h3>Breadcrumbs</h3> Demis / Bellot <h3>Menus</h3> <ul> <li>ServiceStack - http://www.servicestack.net <ul> <li>REST</li> <li>JSON</li> <li>XML</li> </ul></li> <li>AjaxStack - http://www.ajaxstack.com <ul> <li>HTML5</li> <li>AJAX</li> <li>SPA</li> </ul></li> </ul> <h3>HTML Table</h3> <table><caption>Demis's Links</caption><thead><tr><th>Name</th><th>Link</th></tr></thead> <tbody> <tr><td>ServiceStack</td><td>http://www.servicestack.net</td></tr><tr><td>AjaxStack</td><td>http://www.ajaxstack.com</td></tr></tbody> </table> ".Replace("\r\n", "\n"); markdownFormat.MarkdownBaseType = typeof(CustomMarkdownViewBase); markdownFormat.MarkdownGlobalHelpers = new Dictionary <string, Type> { { "Ext", typeof(CustomMarkdownHelper) } }; markdownFormat.RegisterMarkdownPage(new MarkdownPage(markdownFormat, "/path/to/page", "HeaderLinks", headerTemplate)); var dynamicPage = new MarkdownPage(markdownFormat, "/path/to/tpl", "DynamicIfTpl", template); dynamicPage.Prepare(); var templateOutput = dynamicPage.RenderToHtml(templateArgs); templateOutput = templateOutput.Replace("\r\n", "\n"); Console.WriteLine(templateOutput); Assert.That(templateOutput, Is.EqualTo(expectedHtml)); }
private string RenderInTemplateIfAny(MarkdownPage markdownPage, Dictionary <string, object> scopeArgs, string pageHtml, string templatePath = null) { MarkdownTemplate markdownTemplate = null; if (templatePath != null) { MasterPageTemplates.TryGetValue(templatePath, out markdownTemplate); } var directiveTemplate = markdownPage.DirectiveTemplate; if (markdownTemplate == null && directiveTemplate != null) { if (!MasterPageTemplates.TryGetValue(directiveTemplate, out markdownTemplate)) { var templateInSharedPath = "{0}/{1}.shtml".Fmt(SharedDir, directiveTemplate); if (!MasterPageTemplates.TryGetValue(templateInSharedPath, out markdownTemplate)) { var virtualFile = VirtualPathProvider.GetFile(directiveTemplate); if (virtualFile == null) { throw new FileNotFoundException("Could not find template: " + directiveTemplate); } var templateContents = GetPageContents(virtualFile); markdownTemplate = AddTemplate(directiveTemplate, templateContents); } } } if (markdownTemplate == null) { if (markdownPage.Template != null) { MasterPageTemplates.TryGetValue(markdownPage.Template, out markdownTemplate); } if (markdownTemplate == null && templatePath == null) { MasterPageTemplates.TryGetValue(DefaultTemplate, out markdownTemplate); } if (markdownTemplate == null) { if (templatePath == null) { return(pageHtml); } throw new Exception("No template found for page: " + markdownPage.FilePath); } } if (scopeArgs != null) { scopeArgs[MarkdownTemplate.BodyPlaceHolder] = pageHtml; } var htmlPage = markdownTemplate.RenderToString(scopeArgs); return(htmlPage); }
private IVirtualFile GetLatestPage(MarkdownPage markdownPage) { var file = VirtualPathProvider.GetFile(markdownPage.FilePath); return(file); }
public void Register(IAppHost appHost) { if (instance == null) { instance = this; } this.AppHost = appHost; appHost.ViewEngines.Add(this); if (!WatchForModifiedPages) { WatchForModifiedPages = appHost.Config.DebugMode; } foreach (var ns in EndpointHostConfig.RazorNamespaces) { Evaluator.AddAssembly(ns); } this.MarkdownBaseType = appHost.Config.MarkdownBaseType ?? this.MarkdownBaseType; this.MarkdownGlobalHelpers = appHost.Config.MarkdownGlobalHelpers ?? this.MarkdownGlobalHelpers; this.ReplaceTokens = appHost.Config.HtmlReplaceTokens ?? new Dictionary <string, string>(); var webHostUrl = appHost.Config.WebHostUrl; if (!webHostUrl.IsNullOrEmpty()) { this.ReplaceTokens["~/"] = webHostUrl.WithTrailingSlash(); } if (VirtualPathProvider == null) { VirtualPathProvider = AppHost.VirtualPathProvider; } RegisterMarkdownPages(appHost.Config.WebHostPhysicalPath); appHost.CatchAllHandlers.Add((httpMethod, pathInfo, filePath) => { MarkdownPage markdownPage = null; if (catchAllPathsNotFound.Contains(pathInfo)) { return(null); } markdownPage = FindByPathInfo(pathInfo); if (WatchForModifiedPages) { ReloadModifiedPageAndTemplates(markdownPage); } if (markdownPage == null) { if (pathInfo.EndsWith(".md")) { pathInfo = pathInfo.EndsWith(DefaultPage + ".md", StringComparison.InvariantCultureIgnoreCase) ? pathInfo.Substring(0, pathInfo.Length - (DefaultPage + ".md").Length) : pathInfo.WithoutExtension(); return(new RedirectHttpHandler { AbsoluteUrl = webHostUrl.IsNullOrEmpty() ? null : webHostUrl.CombineWith(pathInfo), RelativeUrl = webHostUrl.IsNullOrEmpty() ? pathInfo : null }); } if (catchAllPathsNotFound.Count > 1000) //prevent DDOS { catchAllPathsNotFound = new HashSet <string>(); } var tmp = new HashSet <string>(catchAllPathsNotFound) { pathInfo }; catchAllPathsNotFound = tmp; return(null); } return(new MarkdownHandler(pathInfo) { MarkdownFormat = this, MarkdownPage = markdownPage, RequestName = "MarkdownPage" }); }); appHost.ContentTypeFilters.Register(ContentType.MarkdownText, SerializeToStream, null); appHost.ContentTypeFilters.Register(ContentType.PlainText, SerializeToStream, null); appHost.Config.IgnoreFormatsInMetadata.Add(ContentType.MarkdownText.ToContentFormat()); appHost.Config.IgnoreFormatsInMetadata.Add(ContentType.PlainText.ToContentFormat()); }
public IActionResult ViewPage(string id) { try { MarkdownPage model; // fetch file info var info = _fileProvider.GetFileInfo($"{id}.md"); if (!info.Exists) { return(NotFound()); } if (info.IsDirectory) { return(NotFound()); } // Look for cache key, check last modified date. if (_cache.TryGetValue(_cacheKey + id, out model) && model.LastModified >= info.LastModified) { return(View(model)); } // read out file and parse it using (var fs = info.CreateReadStream()) using (var sr = new StreamReader(fs)) { var source = sr.ReadToEnd(); var frontmatter = Regex.Match(source, @"^---([\s\S]+?)---"); var yamlStream = new StringReader(frontmatter.Groups[1].Value.Trim()); var meta = _metaReader.Deserialize <MarkdownPageMeta>(yamlStream); var html = Markdown.ToHtml(source, _pipeline); model = new MarkdownPage() { Html = html, LastModified = info.LastModified, Meta = meta ?? new MarkdownPageMeta() }; // defaults if (string.IsNullOrWhiteSpace(model.Meta.Title)) { model.Meta.Title = id.Humanize(LetterCasing.Title); } // cache for up to 1 day var options = new MemoryCacheEntryOptions().SetSlidingExpiration(new TimeSpan(1, 0, 0, 0)); _cache.Set(_cacheKey + id, model, options); } return(View(model)); } catch (FileNotFoundException) { return(NotFound()); } }
private string RenderStaticPage(MarkdownPage markdownPage, bool renderHtml) { //TODO: Optimize if contains no dynamic elements return(RenderDynamicPage(markdownPage, new Dictionary <string, object>(), renderHtml, true)); }
public void RegisterMarkdownPage(MarkdownPage markdownPage) { AddPage(markdownPage); }
public static string GetEditPage(MarkdownPage page) { return string.Format(ConfigurationManager.AppSettings.Get("editUrl"), page.FileName); }
public void Register(IAppHost appHost) { if (instance == null) { instance = this; } this.AppHost = appHost; appHost.ViewEngines.Add(this); if (!CheckLastModifiedForChanges) { CheckLastModifiedForChanges = appHost.Config.DebugMode; } foreach (var ns in appHost.Config.RazorNamespaces) { Evaluator.AddAssembly(ns); } this.ReplaceTokens = appHost.Config.HtmlReplaceTokens ?? new Dictionary <string, string>(); var webHostUrl = appHost.Config.WebHostUrl; if (!webHostUrl.IsNullOrEmpty()) { this.ReplaceTokens["~/"] = webHostUrl.WithTrailingSlash(); } if (VirtualPathProvider == null) { VirtualPathProvider = AppHost.VirtualFileSources; } RegisterMarkdownPages(appHost.WebHostPhysicalPath); appHost.CatchAllHandlers.Add((httpMethod, pathInfo, filePath) => { MarkdownPage markdownPage = null; if (catchAllPathsNotFound.Contains(pathInfo)) { return(null); } markdownPage = FindByPathInfo(pathInfo); if (CheckLastModifiedForChanges) { ReloadModifiedPageAndTemplates(markdownPage); } if (markdownPage == null) { if (pathInfo.EndsWith(".md")) { pathInfo = pathInfo.EndsWithIgnoreCase(DefaultPage + ".md") ? pathInfo.Substring(0, pathInfo.Length - (DefaultPage + ".md").Length) : pathInfo.WithoutExtension(); return(new RedirectHttpHandler { AbsoluteUrl = webHostUrl.IsNullOrEmpty() ? null : webHostUrl.AppendPath(pathInfo), RelativeUrl = webHostUrl.IsNullOrEmpty() ? pathInfo : null }); } if (catchAllPathsNotFound.Count > 1000) //prevent DDOS { catchAllPathsNotFound = new HashSet <string>(); } var tmp = new HashSet <string>(catchAllPathsNotFound) { pathInfo }; catchAllPathsNotFound = tmp; return(null); } return(new MarkdownHandler(pathInfo) { MarkdownFormat = this, MarkdownPage = markdownPage, RequestName = "MarkdownPage" }); }); appHost.ContentTypes.RegisterAsync(MimeTypes.MarkdownText, SerializeToStreamAsync, null); appHost.ContentTypes.RegisterAsync(MimeTypes.PlainText, SerializeToStreamAsync, null); appHost.Config.IgnoreFormatsInMetadata.Add(MimeTypes.MarkdownText.ToContentFormat()); appHost.Config.IgnoreFormatsInMetadata.Add(MimeTypes.PlainText.ToContentFormat()); appHost.GetPlugin <MetadataFeature>() ?.AddLink(MetadataFeature.AvailableFeatures, "http://docs.servicestack.net/markdown-razor", "Markdown Razor"); }
public void SetUp() { _mainPage = new MainPage(Driver).GoToMainPage(); _markdown = _mainPage.GoToMarkdownPage(); }
public void WritePage(MarkdownPage page) { WriteFile(page); }
private void ValidatePage(MarkdownPage page) { if (string.IsNullOrEmpty(page.Title)) AddValidationError(page, "Title must be set"); if (string.IsNullOrEmpty(page.Description)) AddValidationError(page, "Description must be set"); if (string.IsNullOrEmpty(page.Slug)) AddValidationError(page, "Slug must be set"); else if (page.Slug.Any(c => char.IsUpper(c) || char.IsWhiteSpace(c) || char.IsSymbol(c))) AddValidationError(page, "Slug must be alphanumeric and lower case only"); if (string.IsNullOrEmpty(page.Keywords) || page.Keywords.Count(c => c == ',') < 2) AddValidationError(page, "At least 3 comma separated keywords must be specified"); }
public void Can_capture_Section_statements_and_store_them_in_scopeargs() { var template = @"## Welcome to Razor! @var lastName = Model.LastName; @section Salutations { Hello @Upper(lastName), @Model.FirstName } @section Breadcrumbs { ### Breadcrumbs @Combine("" / "", Model.FirstName, lastName) } @var links = Model.Links @section Menus { ### Menus @foreach (var link in links) { - @link.Name - @link.Href @var labels = link.Labels @foreach (var label in labels) { - @label } } } ## Captured Sections <div id='breadcrumbs'>@Breadcrumbs</div> @Menus ## Salutations @Salutations "; var expectedHtml = @"<h2>Welcome to Razor!</h2> <h2>Captured Sections</h2> <div id='breadcrumbs'><h3>Breadcrumbs</h3> <p>Demis / Bellot</p> </div> <p><h3>Menus</h3> <ul> <li>ServiceStack - http://www.servicestack.net <ul> <li>REST</li> <li>JSON</li> <li>XML</li> </ul></li> <li>AjaxStack - http://www.ajaxstack.com <ul> <li>HTML5</li> <li>AJAX</li> <li>SPA</li> </ul></li> </ul> </p> <h2>Salutations</h2> <p><p>Hello BELLOT, Demis</p> </p> ".Replace("\r\n", "\n"); var dynamicPage = new MarkdownPage(markdownFormat, "/path/to/tpl", "DynamicModelTpl", template); dynamicPage.Prepare(); var templateOutput = dynamicPage.RenderToHtml(templateArgs); templateOutput = templateOutput.Replace("\r\n", "\n"); Assert.That(dynamicPage.ExecutionContext.BaseType, Is.EqualTo(typeof(MarkdownViewBase))); Console.WriteLine(templateOutput); Assert.That(templateArgs["Salutations"].ToString(), Is.EqualTo("<p>Hello BELLOT, Demis</p>\n")); Assert.That(templateOutput, Is.EqualTo(expectedHtml)); }
public MarkdownPageViewModel(IHtmlContent tryDotNetSrc, string hostOrigin, MarkdownPage page) => (TryDotNetSrc, HostOrigin, Page) = (tryDotNetSrc, hostOrigin, page);
public static string GetEditPage(MarkdownPage page) { return(string.Format(ConfigurationManager.AppSettings.Get("editUrl"), page.FileName)); }
public void Transform(MarkdownPage input) { input.Contents = LinkRegex.Replace(input.Contents, @"<a href=""/$1"">$1</a>"); }
private void AddValidationError(MarkdownPage page, string message) { ValidationMessages.Add(string.Format(message + " | " + page.FileName)); IsValid = false; }