public Site(SiteConfig config, IEnumerable<DataFile> data, IEnumerable<DocumentFile> documents, IEnumerable<StaticFile> files, LayoutFileCollection layouts, Site parent = null) { this.DefaultLayoutForExtension = new Dictionary<string, string>(config.DefaultLayoutForExtension); this.IgnoreFiles = config.IgnoreFiles; this.SitePath = config.SitePath; this.Author = config.Author; this.LiveReloadScript = config.LiveReloadScript; this.DocumentsPath = config.DocumentsPath; this.FilesPath = config.FilesPath; this.LayoutsPath = config.LayoutsPath; this.OutputPath = config.OutputPath; this.Parent = parent; this.TimeZone = config.TimeZone; this.Url = config.Url.EnsureEndsWith("/"); this.RootUrl = config.RootUrl.EnsureEndsWith("/"); var allDocuments = documents.ToList(); this.Data = data.ToList(); this.Partials = allDocuments.Where(d => d.Partial).ToList(); this.Documents = allDocuments.Where(d => !d.Partial).ToList(); this.Files = files.ToList(); this.Layouts = new LayoutFileCollection(layouts); this.Metadata = config.Metadata; }
public void CanParseQuery() { var config = new SiteConfig() { RootUrl = String.Empty, Url = "http://www.example.com" }; var documents = new[] { new DocumentFile("bar.html.md", Path.GetFullPath("documents"), "documents", "documents", "bar", "bar", null, new MetadataCollection(), null), new DocumentFile("foo.html.md", Path.GetFullPath("documents"), "documents", "documents", "foo", "foo", null, new MetadataCollection(), null), }; var site = new Site(config, Enumerable.Empty<DataFile>(), documents, Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); var query = @"query documents every 10 where sourcerelativepath startswith ""documents\posts\"" descending date formaturl ""posts/page/{0}"""; var result = QueryProcessor.Parse(site, query); Assert.Equal(2, result.Source.Count()); Assert.Equal(10, result.PageEvery); Assert.Equal(WhereOperator.StartsWith, result.Where.Operator); Assert.Equal("sourcerelativepath", result.Where.Property); Assert.Equal(@"documents\posts\", result.Where.Value); Assert.Equal(OrderOperator.Descending, result.Order.Operator); Assert.Equal("date", result.Order.Property); Assert.Equal(@"posts/page/{0}", result.FormatUrl); var q = result.Results.ToList(); Assert.Empty(q); }
public void CanGetDefaultLayout() { var command = new LoadSiteConfigCommand() { ConfigPath = "data\\site.config" }; var config = command.Execute(); var site = new Site(config, Enumerable.Empty<DataFile>(), Enumerable.Empty<DocumentFile>(), Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); Assert.Equal("test", site.DefaultLayoutForExtension["html"]); }
public void CanGetFullUrlFromData() { var command = new LoadSiteConfigCommand() { ConfigPath = "data\\site.config" }; var config = command.ExecuteAsync().Result; var site = new Site(config, Enumerable.Empty<DataFile>(), Enumerable.Empty<DocumentFile>(), Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); dynamic data = site; //site.GetAsDynamic(); Assert.Equal("http://www.example.com/blog/", data.fullurl); }
public void CanGetDefaultUrlFromData() { var command = new LoadSiteConfigCommand() { ConfigPath = "data\\site.config" }; var config = command.Execute(); var site = new Site(config, Enumerable.Empty<DataFile>(), Enumerable.Empty<DocumentFile>(), Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); dynamic data = site; //site.GetAsDynamic(); Assert.Equal("/blog/", data.Url); }
public void CanRenderDocument() { var tinySiteAssembly = typeof(RazorRenderer).Assembly; var basePath = Path.GetFullPath(@"data\RenderDocumentsCommand\"); var outputPath = Path.Combine(Path.GetTempPath(), @"tinysite\"); var loadLayouts = new LoadLayoutsCommand(Path.Combine(basePath, @"layouts\"), null, null); var layouts = loadLayouts.Execute(); var collection = new LayoutFileCollection(layouts); var loadDocuments = new LoadDocumentsCommand(); loadDocuments.Author = new Author(); loadDocuments.DocumentsPath = Path.Combine(basePath, @"documents\"); loadDocuments.Layouts = collection; loadDocuments.OutputRootPath = outputPath; loadDocuments.RenderedExtensions = new[] { "md", "cshtml" }; loadDocuments.RootUrl = "http://www.example.com/"; loadDocuments.ApplicationUrl = "/app/sub"; var documents = loadDocuments.Execute().OrderBy(d => d.Name).ToList(); var config = new SiteConfig() { OutputPath = outputPath, Url = "http://example.com", RootUrl = String.Empty, }; var site = new Site(config, Enumerable.Empty<DataFile>(), documents, Enumerable.Empty<StaticFile>(), collection); var engines = RenderingEngine.Load(tinySiteAssembly); Statistics.Current = new Statistics(); var command = new RenderDocumentsCommand(engines, site); command.Execute(); var description = "This is the summary of the document with a link to example.com."; var content = "<p>This is the summary of the document with a link to <a href=\"http://example.com\">example.com</a>.</p>\n<p>This is additional content in the document.</p>"; var summary = "<p>This is the summary of the document with a link to <a href=\"http://example.com\">example.com</a>.</p>"; var title = "test"; Assert.Equal(0, command.RenderedData); Assert.Equal(3, command.RenderedDocuments); Assert.Equal(String.Empty, documents[0].RenderedContent.Trim()); Assert.Equal("This is the summary of the document with a link to [example.com](http://example.com).\n\nThis is additional content in the document.", documents[2].SourceContent.Replace("\r\n", "\n")); Assert.Equal(content, documents[2].Content); Assert.Equal(description, documents[2].Description); Assert.Equal(summary, documents[2].Summary); Assert.Equal(title, documents[2].Metadata.Get<string>("title")); Assert.Equal( $"<title>{title}</title>\n" + $"<description>{description}</description>\n" + $"<summary>{summary}</summary>\n" + $"<content>{content}</content>", documents[2].RenderedContent.Replace("\r\n", "\n")); }
public void CanGetTitle() { var command = new LoadSiteConfigCommand() { ConfigPath = "data\\site.config" }; var config = command.ExecuteAsync().Result; var site = new Site(config, Enumerable.Empty<DataFile>(), Enumerable.Empty<DocumentFile>(), Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); dynamic data = new DynamicSite(null, site); Assert.Equal("Test Blog.", (string)data.tiTle); }
public RenderingTransaction(IDictionary<string, RenderingEngine> engines, Site site) { if (RenderingTransaction.Current != null) { throw new InvalidOperationException("Can only have one rendering transaction active at a time. Ensure the previous rendering transaction was disposed before creating this one."); } this.Engines = engines; this.Site = site; this.Documents = site.Documents; this.Files = site.Files; this.Layouts = site.Layouts; RenderingTransaction.Current = this; }
public void CanDoQueryableMultipleWhere() { var config = new SiteConfig() { RootUrl = String.Empty, Url = "http://www.example.com" }; var meta1 = new MetadataCollection { { "number", 1 }, { "canonical", null } }; var meta2 = new MetadataCollection { { "number", 20 }, { "canonical", "true" } }; var meta3 = new MetadataCollection { { "number", 3 }, { "canonical", null } }; var documents = new[] { new DocumentFile("1.html.md", Path.GetFullPath("documents"), "documents", "1", "1", String.Empty, null, meta1, null), new DocumentFile("20.html.md", Path.GetFullPath("documents"), "documents", "20", "20", String.Empty, null, meta2, null), new DocumentFile("3.html.md", Path.GetFullPath("documents"), "documents", "3", "3", String.Empty, null, meta3, null), }; var site = new Site(config, Enumerable.Empty<DataFile>(), documents, Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); var query = @"query documents where number gt 1 where canonical equals null ascending number"; var p = QueryProcessor.Parse(site, query); var q = p.Results.ToList(); Assert.Single(q); Assert.Equal(3, q[0].Number); }
private IEnumerable<LastRunDocument> CalculateLastRunState(Site site) { var dt = this.InitialLastRunState.ToDictionary(l => l.Path); foreach (var document in site.Documents.Where(d => !d.Cloned && !d.Unmodified)) { var contributors = document.AllContributingFiles() .Select(d => new LastRunContributingFile(d.SourceRelativePath, d.Modified)); var lastRunDocument = new LastRunDocument(document.SourceRelativePath, document.Modified, contributors); dt.Remove(document.SourceRelativePath); yield return lastRunDocument; } foreach (var lrd in dt.Values) { yield return lrd; } }
public void CanReadDynamicRenderingData() { var sitePath = @"C:\site\"; var documentsPath = sitePath + @"documents\"; var layoutsPath = sitePath + @"layouts\"; var outputPath = sitePath + @"build\"; var document = new DocumentFile(documentsPath + "foo.html.md", documentsPath, outputPath + "foo.html", outputPath, String.Empty, String.Empty, null, null, null); var layout = new LayoutFile(layoutsPath + "default.cshtml", layoutsPath, String.Empty, null, null); var config = new SiteConfig() { OutputPath = outputPath, Url = "http://example.com", RootUrl = String.Empty, }; var site = new Site(config, Enumerable.Empty<DataFile>(), new[] { document }, Enumerable.Empty<StaticFile>(), new LayoutFileCollection(new[] { layout })); dynamic data = new DynamicRenderDocument(document, layout, site); Assert.Equal(outputPath, data.Site.OutputPath); Assert.Single(data.Site.Documents); foreach (var d in data.Site.Documents) { Assert.Equal(outputPath + "foo.html", d.OutputPath); } }
public void CanDoQueryable() { var config = new SiteConfig() { RootUrl = String.Empty, Url = "http://www.example.com" }; var documents = new[] { new DocumentFile("bar.html.md", Path.GetFullPath("documents"), "documents", "documents", "bar", "bar", null, new MetadataCollection(), null), new DocumentFile("foo.html.md", Path.GetFullPath("documents"), "documents", "documents", "foo", "foo", null, new MetadataCollection(), null), }; var site = new Site(config, Enumerable.Empty<DataFile>(), documents, Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); var query = @"query documents where outputpath startswith ""doc"" descending url"; var p = QueryProcessor.Parse(site, query); var q = p.Results.ToList(); Assert.Equal("foo/foo", q[0].Url); Assert.Equal("bar/bar", q[1].Url); }
public static QueryResult Parse(Site site, string query) { var dynamicSite = new DynamicSite(null, site); var result = new QueryResult(); // query documents every 10 where relativepath startswith "documents\posts\" descending date formaturl "posts/page/{0}" var tokens = ParseTokens(query).ToArray(); for (int i = 0; i < tokens.Length; ++i) { var token = tokens[i].ToLowerInvariant(); switch (token) { case "query": result.Source = ParseSource(dynamicSite, tokens, ref i); break; case "ascending": case "descending": result.Order = ParseOrder(tokens, ref i); break; case "every": result.PageEvery = ParseEvery(tokens, ref i); break; case "formaturl": result.FormatUrl = ParseFormatUrl(tokens, ref i); break; case "take": result.Take = ParseTake(tokens, ref i); break; case "where": result.Where = ParseWhere(tokens, ref i); break; default: throw new InvalidOperationException(String.Format("Unknown query token: {0}", token)); } } var q = result.Source.AsQueryable(); if (result.Where != null) { q = q.Cast<IDictionary<string, object>>().Where(e => WhereQuery(result.Where, e)); } if (result.Order != null) { if (result.Order.Operator == OrderOperator.Ascending) { q = q.Cast<IDictionary<string, object>>().OrderBy(e => OrderProperty(result.Order, e)); } else { q = q.Cast<IDictionary<string, object>>().OrderByDescending(e => OrderProperty(result.Order, e)); } } if (result.Take > 0) { q = q.Take(result.Take); } result.Results = q; return result; }
public RenderDocumentsCommand(IDictionary<string, RenderingEngine> engines, Site site) { this.Engines = engines; this.Site = site; }
private void Order(Site site) { using (var capture = Statistics.Current.Start(StatisticTiming.Ordering)) { var order = new OrderCommand(); order.Documents = site.Documents; order.Execute(); site.Books = order.Books; } }
public void CanDoQueryableNumeric() { var config = new SiteConfig() { RootUrl = String.Empty, Url = "http://www.example.com" }; var meta1 = new MetadataCollection(); meta1.Add("number", 1); var meta2 = new MetadataCollection(); meta2.Add("number", 20); var meta3 = new MetadataCollection(); meta3.Add("number", 3); var documents = new[] { new DocumentFile("1.html.md", Path.GetFullPath("documents"), "documents", "1", "1", String.Empty, null, meta1, null), new DocumentFile("20.html.md", Path.GetFullPath("documents"), "documents", "20", "20", String.Empty, null, meta2, null), new DocumentFile("3.html.md", Path.GetFullPath("documents"), "documents", "3", "3", String.Empty, null, meta3, null), }; var site = new Site(config, Enumerable.Empty<DataFile>(), documents, Enumerable.Empty<StaticFile>(), Enumerable.Empty<LayoutFile>()); var query = @"query documents where number gt 1 ascending number"; var p = QueryProcessor.Parse(site, query); var q = p.Results.ToList(); Assert.Equal(3, q[0].Number); Assert.Equal(20, q[1].Number); }
private void Paginate(Site site) { using (var capture = Statistics.Current.Start(StatisticTiming.Pagination)) { var paginate = new PaginateCommand(); paginate.RootUrl = site.Url; paginate.Site = site; paginate.Execute(); foreach (var doc in paginate.PagedDocuments) { site.Documents.Add(doc); ++Statistics.Current.PagedFiles; } } }
public Site(SiteConfig config, IEnumerable<DataFile> data, IEnumerable<DocumentFile> documents, IEnumerable<StaticFile> files, IEnumerable<LayoutFile> layouts, Site parent = null) : this(config, data, documents, files, new LayoutFileCollection(layouts), parent) { }
private Site LoadSite(SiteConfig config, IEnumerable<LastRunDocument> lastRunState, IEnumerable<string> renderedExtensions) { Site site; using (var capture = Statistics.Current.Start(StatisticTiming.LoadedSite)) { // Load layouts. LayoutFileCollection layouts; { var load = new LoadLayoutsCommand(config.LayoutsPath, config.AdditionalMetadataForFiles, config.IgnoreFiles); var loaded = load.Execute(); layouts = new LayoutFileCollection(loaded); } // Load data files. IEnumerable<DataFile> data; { var load = new LoadDataFilesCommand(config.DataPath, config.AdditionalMetadataForFiles, config.IgnoreFiles); data = load.Execute(); } // Load documents. IEnumerable<DocumentFile> documents; { var load = new LoadDocumentsCommand(); load.Author = config.Author; load.OutputRootPath = config.OutputPath; load.Layouts = layouts; load.RenderedExtensions = renderedExtensions; load.DefaultLayoutForExtension = config.DefaultLayoutForExtension; load.DocumentsPath = config.DocumentsPath; load.RootUrl = config.RootUrl; load.ApplicationUrl = config.Url; load.AdditionalMetadataForFiles = config.AdditionalMetadataForFiles; load.IgnoreFiles = config.IgnoreFiles; documents = load.Execute(); } // Load files. IEnumerable<StaticFile> files; { var load = new LoadFilesCommand(); load.OutputPath = config.OutputPath; load.FilesPath = config.FilesPath; load.RootUrl = config.RootUrl; load.Url = config.Url; files = load.Execute(); } // Calculate unmodified state. { var unmodified = new SetUnmodifiedCommand(config.SitePath, documents, files, this.InitialLastRunState); unmodified.Execute(); } site = new Site(config, data, documents, files, layouts); } Statistics.Current.SiteFiles = site.Documents.Count + site.Files.Count + site.Layouts.Count; return site; }
private void Render(Site site, IDictionary<string, RenderingEngine> engines) { using (var rendering = Statistics.Current.Start(StatisticTiming.Rendered)) { using (var capture = Statistics.Current.Start(StatisticTiming.RenderDocuments)) { var render = new RenderDocumentsCommand(engines, site); render.Execute(); Statistics.Current.RenderedData = render.RenderedData; Statistics.Current.RenderedDocuments = render.RenderedDocuments; } using (var capture = Statistics.Current.Start(StatisticTiming.WriteDocuments)) { var write = new WriteDocumentsCommand(site.Documents); write.Execute(); Statistics.Current.WroteDocuments = write.WroteDocuments; } using (var capture = Statistics.Current.Start(StatisticTiming.CopyStaticFiles)) { var copy = new CopyStaticFilesCommand(site.Files); copy.Execute(); Statistics.Current.CopiedFiles = copy.CopiedFiles; } } }