public override ContentResult TryProcessContent(ContentObject file, ContentProcessingStage stage) { var contentType = file.ContentType; if (!Plugin.Enable || !contentType.IsHtmlLike()) { return(ContentResult.Continue); } // if sitemap is false, then don't index it var allowSiteMap = file["sitemap"] is bool v ? v : true; if (!allowSiteMap) { return(ContentResult.Continue); } var url = Site.Builtins.UrlRef((ContentObject)null, file.Url); var sitemapUrl = new SitemapUrl(url) { LastModified = file.ModifiedTime.Ticks == 0 ? DateTime.Now : file.ModifiedTime }; _urlSet.Urls.Add(sitemapUrl); return(ContentResult.Continue); }
public override ContentResult TryProcessContent(ContentObject page, ContentProcessingStage stage) { Debug.Assert(stage == ContentProcessingStage.Processing); // Work only on single layout type if (page.LayoutType != ContentPlugin.SingleLayoutType) { return(ContentResult.Continue); } SummarizerHelper.UpdateSummary(page); // Allow further processing of this page return(ContentResult.Continue); }
public override ContentResult TryProcessContent(ContentObject file, ContentProcessingStage stage) { Debug.Assert(stage == ContentProcessingStage.Running); if (!_isInitialized) { return(ContentResult.Continue); } var contentType = file.ContentType; // This plugin is only working on scss files if (!contentType.IsHtmlLike()) { return(ContentResult.Continue); } // Exclude any files that are globally excluded foreach (var searchPattern in _excludes) { if (searchPattern.Match(file.Path)) { return(ContentResult.Continue); } } if (file.Content == null) { file.Content = file.SourceFile.ReadAllText(); } var plainText = contentType == ContentType.Markdown ? Markdown.ToHtml(file.Content) : file.Content; // Remove any HTML from existing content plainText = contentType == ContentType.Markdown ? NUglify.Uglify.HtmlToText($"<html><body>{plainText}</body></html>").Code : NUglify.Uglify.HtmlToText(plainText).Code; // Remove any trailing plainText = FindSpacesRegexp.Replace(plainText, " ").Trim(); ProcessSearchContent(file, plainText); return(ContentResult.Continue); }
public override ContentResult TryProcessContent(ContentObject page, ContentProcessingStage stage) { Debug.Assert(stage == ContentProcessingStage.Processing); var contentType = page.ContentType; // This plugin is only working on files with a frontmatter and the markdown extension if (!page.HasFrontMatter || contentType != ContentType.Markdown) { return(ContentResult.None); } var html = ToHtml(page, GetPipeline()); page.Content = html; page.ChangeContentType(ContentType.Html); // Allow further processing of this page return(ContentResult.Continue); }
public override ContentResult TryProcessContent(ContentObject page, ContentProcessingStage stage) { Debug.Assert(stage == ContentProcessingStage.Running); _pages.Add(page.Path, page); if (page.Path.GetName() != MenuFileName) { return(ContentResult.Continue); } // The menu file is not copied to the output! page.Discard = true; var rawMenu = YamlUtil.FromText(page.SourceFile.ReadAllText(), page.SourceFile.FullName); DecodeMenu(rawMenu, page); return(ContentResult.Break); }
public abstract ContentResult TryProcessContent(ContentObject file, ContentProcessingStage stage);
public override ContentResult TryProcessContent(ContentObject page, ContentProcessingStage stage) { Debug.Assert(stage == ContentProcessingStage.Processing); if (page.ScriptObjectLocal == null) { return(ContentResult.None); } var layoutName = page.Layout ?? page.Section; layoutName = NormalizeLayoutName(layoutName, true); var layoutType = page.LayoutType; var layoutNames = new HashSet <string>() { layoutName }; var result = ContentResult.Continue; // For a list rendering the pages is setup if (layoutType == LayoutTypes.List) { page.ScriptObjectLocal.SetValue("pages", Site.Pages, true); } bool continueLayout; do { continueLayout = false; // TODO: We are using content type here with the layout extension, is it ok? var layoutObject = GetLayout(layoutName, layoutType, page.ContentType); // If we haven't found any layout, this is not an error, so we let the // content as-is if (layoutObject == null) { Site.Warning($"No layout found for content [{page.Url}] with layout name [{layoutName}] and type [{layoutType}]"); break; } // Add dependency to the layout file page.Dependencies.Add(new FileContentDependency(new FileEntry(Site.FileSystem, layoutObject.SourceFile.Path))); // Override playground object layoutObject.CopyToWithReadOnly(page.ScriptObjectLocal); layoutObject.ScriptObjectLocal?.CopyToWithReadOnly(page.ScriptObjectLocal); // Clear the layout object to make sure it is not changed when processing layout between pages page.ScriptObjectLocal.SetValue(PageVariables.Page, page, true); page.ScriptObjectLocal.SetValue(PageVariables.Content, page.Content, false); // We manage global locally here as we need to push the local variable ScriptVariable.BlockDelegate if (Site.Scripts.TryEvaluatePage(page, layoutObject.Script, layoutObject.SourceFile.Path, page.ScriptObjectLocal)) { var nextLayoutName = layoutObject.GetSafeValue <string>(PageVariables.Layout); var nextLayoutType = layoutObject.GetSafeValue <string>(PageVariables.LayoutType); var nextLayout = NormalizeLayoutName(nextLayoutName, false); if (nextLayout != layoutName && nextLayout != null) { if (!layoutNames.Add(nextLayout)) { Site.Error($"Invalid recursive layout `{nextLayout}` from script `{layoutObject.SourceFile.Path}`"); result = ContentResult.Break; break; } layoutName = nextLayout; layoutType = nextLayoutType ?? layoutType; continueLayout = true; } } } while (continueLayout); // The file has been correctly layout return(result); }
private bool TryProcessPage(ContentObject page, ContentProcessingStage stage, IEnumerable <IContentProcessor> pageProcessors, OrderedList <IContentProcessor> pendingPageProcessors, bool copyOutput) { // If page is discarded, skip it if (page.Discard) { return(false); } // By default working on all processors // Order is important! pendingPageProcessors.AddRange(pageProcessors); bool hasBeenProcessed = true; bool breakProcessing = false; // We process the page going through all IContentProcessor from the end of the list // (more priority) to the beginning of the list (less priority). // An IContentProcessor can transform the page to another type of content // that could then be processed by another IContentProcessor // But we make sure that a processor cannot process a page more than one time // to avoid an infinite loop var clock = Stopwatch.StartNew(); while (hasBeenProcessed && !breakProcessing && !page.Discard) { hasBeenProcessed = false; for (int i = pendingPageProcessors.Count - 1; i >= 0; i--) { var processor = pendingPageProcessors[i]; // Note that page.ContentType can be changed by a processor // while processing a page clock.Restart(); try { var result = processor.TryProcessContent(page, stage); if (result != ContentResult.None) { // Update statistics per plugin var statistics = Site.Statistics; var stat = statistics.GetPluginStat(processor); stat.PageCount++; stat.ContentProcessTime += clock.Elapsed; hasBeenProcessed = true; pendingPageProcessors.RemoveAt(i); breakProcessing = result == ContentResult.Break; break; } } catch (Exception ex) { if (ex is LunetException lunetEx) { Site.Error($"Error while processing {page.Path} by {processor.Name} processor. {lunetEx.Message}"); } else { Site.Error(ex, $"Error while processing {page.Path} by {processor.Name} processor."); } breakProcessing = true; hasBeenProcessed = true; break; } } } pendingPageProcessors.Clear(); // Copy only if the file are marked as include if (copyOutput && !breakProcessing && !page.Discard) { Site.Content.TryCopyContentToOutput(page, page.GetDestinationPath()); } return(true); }
public override ContentResult TryProcessContent(ContentObject file, ContentProcessingStage stage) { var contentType = file.ContentType; // This plugin is only working on scss files if (contentType != ScssType) { return(ContentResult.None); } if (file.Content == null) { file.Content = file.SourceFile.ReadAllText(); } var content = file.Content; var options = new ScssOptions(); options.InputFile = (string)file.Path; var includePaths = new List <DirectoryEntry>(); foreach (var pathObj in Plugin.Includes) { var path = pathObj as string; if (path != null && UPath.TryParse(path, out var validPath) && Site.MetaFileSystem.DirectoryExists(validPath)) { includePaths.Add(new DirectoryEntry(Site.MetaFileSystem, validPath)); } else { Site.Error($"Invalid folder path `{pathObj}` found in site.scss.includes."); } } var tempIncludePaths = new List <DirectoryEntry>(); var extensions = new string[] { ".scss", ".sass", ".css" }; var includedFiles = new List <FileEntry>(); options.TryImport = (ref string file, string parentpath, out string scss, out string map) => { scss = null; map = null; // From: https://sass-lang.com/documentation/at-rules/import#load-paths // Imports will always be resolved relative to the current file first, though. // Load paths will only be used if no relative file exists that matches the import. // This ensures that you can’t accidentally mess up your relative imports when you add a new library. tempIncludePaths.Clear(); UPath filePath = (UPath)file; var directoryName = ((UPath)parentpath).GetDirectory(); if (!directoryName.IsNull && directoryName.IsAbsolute) { DirectoryEntry localDirEntry = null; if (Site.FileSystem.DirectoryExists(directoryName)) { localDirEntry = new DirectoryEntry(Site.FileSystem, directoryName); if (!tempIncludePaths.Contains(localDirEntry)) { tempIncludePaths.Add(localDirEntry); } } if (Site.MetaFileSystem.DirectoryExists(directoryName)) { localDirEntry = new DirectoryEntry(Site.MetaFileSystem, directoryName); if (!tempIncludePaths.Contains(localDirEntry)) { tempIncludePaths.Add(localDirEntry); } } } tempIncludePaths.AddRange(includePaths); // From libsass, order for ambiguous import: // (1) filename as given // (2) underscore + given // (3) underscore + given + extension // (4) given + extension // (5) given + _index.scss // (6) given + _index.sass var ufile = (UPath)file; var relativeFolder = ufile.GetDirectory(); var filename = ufile.GetName(); bool Resolve(FileEntry entry, out string scss, out string file) { scss = null; file = null; if (entry.Exists) { scss = entry.ReadAllText(); file = (string)entry.Path; includedFiles.Add(entry); return(true); } return(false); } foreach (var dirEntry in tempIncludePaths) { var rootFolder = dirEntry.Path / relativeFolder; // (1) filename as given if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / filename), out scss, out file)) { return(true); } // (2) underscore + given if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"_{filename}"), out scss, out file)) { return(true); } // (3) underscore + given + extension foreach (var extension in extensions) { if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"_{filename}{extension}"), out scss, out file)) { return(true); } } // (4) given + extension foreach (var extension in extensions) { if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"{filename}{extension}"), out scss, out file)) { return(true); } } // (5) given + _index.scss if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"{filename}" / "_index.scss"), out scss, out file)) { return(true); } // (6) given + _index.sass if (Resolve(new FileEntry(dirEntry.FileSystem, rootFolder / $"{filename}" / "_index.sass"), out scss, out file)) { return(true); } } return(false); }; var result = SharpScss.Scss.ConvertToCss(content, options); file.Content = result.Css; file.ChangeContentType(ContentType.Css); foreach (var includeFile in includedFiles) { file.Dependencies.Add(new FileContentDependency(includeFile)); } return(ContentResult.Continue); }