Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
 public abstract ContentResult TryProcessContent(ContentObject file, ContentProcessingStage stage);
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);
        }