public ArticleDto ParseArticleRawText(string sourceText, string relativePath)
 {
     ArticleDto article = new ArticleDto(@"Articles\MyArticle.md", this);
     article.Content =
     @"#My Article
     Some important text";
     article.Attributes = new Dictionary<string, IList<string>>();
     article.Attributes.Add("Title", new List<string>());
     article.Attributes["Title"].Add("My Great Article");
     return article;
 }
示例#2
0
        public void LoadArticleBadDate()
        {
            string input =
                @"---
Title:MyArticle
Date:XXXXXX
---
##The internals
Some article content...
";
            MarkdownArticleProcessor ar = new MarkdownArticleProcessor(getAttributeSet());
            ArticleDto output           = ar.ParseArticleRawText(input, "TestArticle");

            Assert.AreEqual(1, output.Attributes.Count);
            Assert.AreEqual("MyArticle", output.Attributes["Title"][0]);
        }
示例#3
0
        public void LoadArticlePositive()
        {
            string input =
                @"---
Title:MyArticle
Date:2015-01-02
---
##The internals
Some article content...
";
            MarkdownArticleProcessor ar = new MarkdownArticleProcessor(getAttributeSet());
            ArticleDto output           = ar.ParseArticleRawText(input, "TestArticle");

            Assert.AreEqual(2, output.Attributes.Count);
            Assert.AreEqual("MyArticle", output.Attributes["Title"][0]);
            Assert.AreEqual("2015-01-02", output.Attributes["Date"][0]);
            Assert.AreEqual("##The internals\r\nSome article content...\r\n\r\n", output.Content);
        }
        /// <summary>
        /// Determines the correct output path for an article.
        /// </summary>
        /// <param name="article">The article whose path is to be calculated. This object is not updated.</param>
        /// <returns>The new article output path.</returns>
        public static string CalculateArticlePath(ArticleDto article)
        {
            if(article.Attributes.Any(x => x.Key == "Path" && x.Value.Count > 0))
            {
                string path = article.Attributes.First(x => x.Key == "Path").Value[0];
                if(path.IndexOfAny(Path.GetInvalidPathChars()) > -1)
                {
                    Logger.LogWarning("Article " + article.SourceFileRelativePath + " specified invalid path " + path + " which was ignored.");
                }
                else
                {
                    return path.Replace('\\', '/');
                }
            }

            string noExtPath = Path.GetDirectoryName(article.SourceFileRelativePath) + "/" + Path.GetFileNameWithoutExtension(article.SourceFileRelativePath);
            noExtPath = noExtPath.Replace('\\', '/');
            noExtPath += ".html";
            return noExtPath;
        }
示例#5
0
        /// <summary>
        /// Determines the correct output path for an article.
        /// </summary>
        /// <param name="article">The article whose path is to be calculated. This object is not updated.</param>
        /// <returns>The new article output path.</returns>
        public static string CalculateArticlePath(ArticleDto article)
        {
            if (article.Attributes.Any(x => x.Key == "Path" && x.Value.Count > 0))
            {
                string path = article.Attributes.First(x => x.Key == "Path").Value[0];
                if (path.IndexOfAny(Path.GetInvalidPathChars()) > -1)
                {
                    Logger.LogWarning("Article " + article.SourceFileRelativePath + " specified invalid path " + path + " which was ignored.");
                }
                else
                {
                    return(path.Replace('\\', '/'));
                }
            }

            string noExtPath = Path.GetDirectoryName(article.SourceFileRelativePath) + "/" + Path.GetFileNameWithoutExtension(article.SourceFileRelativePath);

            noExtPath  = noExtPath.Replace('\\', '/');
            noExtPath += ".html";
            return(noExtPath);
        }
示例#6
0
        public void ExpandArticleMacrosTest()
        {
            MarkdownArticleProcessor ar = new MarkdownArticleProcessor(getAttributeSet());
            ArticleDto a = ar.ParseArticleRawText(
            @"---
            Title:Xbox Controller Repair
            Date:2014-08-02
            Category:Electronics
            Tags:Gaming,Electronics
            ---
            ##The internals
            ![:youtube 800 600](https://www.youtube.com/embed/Di5AT4MI6BY)
            ![:youtube 512 400](http://www.youtube.com/embed/Di5AT4MI6BY)", "Some\\File.md");

            MacroInvocation mi = ar.LocateMacrosInContent(a)[0];
            MarkdownMacro mdm = new MarkdownMacro("youtube", "<iframe width=\"%p1%\" height=\"%p2%\" src=\"%v1%\" frameborder=\"0\"></iframe>");
            ArticleDto[] allArticles = new ArticleDto[1];
            allArticles[0] = a;
            string finalText = mdm.Expand(mi.Parameters, mi.Values, a, allArticles);
            Assert.AreEqual(
            "<iframe width=\"800\" height=\"600\" src=\"https://www.youtube.com/embed/Di5AT4MI6BY\" frameborder=\"0\"></iframe>",
            finalText.Trim());
        }
示例#7
0
        public void ExpandMacroTest()
        {
            MarkdownArticleProcessor ar = new MarkdownArticleProcessor(getAttributeSet());
            ArticleDto a = ar.ParseArticleRawText(
                @"---
Title:Xbox Controller Repair
Date:2014-08-02
Category:Electronics
Tags:Gaming,Electronics
---
![:youtube 800 600](https://www.youtube.com/embed/Di5AT4MI6BY)", "Some\\File.md");

            MacroInvocation mi  = ar.LocateMacrosInContent(a)[0];
            MarkdownMacro   mdm = new MarkdownMacro("youtube", "<iframe width=\"%p1%\" height=\"%p2%\" src=\"%v1%\" frameborder=\"0\"></iframe>");

            ArticleDto[] allArticles = new ArticleDto[1];
            allArticles[0] = a;
            string finalText = mdm.Expand(mi.Parameters, mi.Values, a, allArticles);

            Assert.AreEqual(
                "<iframe width=\"800\" height=\"600\" src=\"https://www.youtube.com/embed/Di5AT4MI6BY\" frameborder=\"0\"></iframe>",
                finalText.Trim());
        }
        public void LocateMacro()
        {
            MarkdownArticleProcessor ar = new MarkdownArticleProcessor(getAttributeSet());
            ArticleDto a = ar.ParseArticleRawText(
            @"---
            Title:Xbox Controller Repair
            Date:2014-08-02
            Category:Electronics
            Tags:Gaming,Electronics
            ---
            ##The internals
            ![:youtube 800 600](https://www.youtube.com/embed/Di5AT4MI6BY)
            ![:youtube 512 400](http://www.youtube.com/embed/Di5AT4MI6BY)
            ![My image caption](imgs/someImageNotAMacro.jpg", "Some\\File.md");

            MacroInvocation mi = ar.LocateMacrosInContent(a)[0];
            MarkdownMacro mdm = new MarkdownMacro("youtube", "<iframe width=\"%p1%\" height=\"%p2%\" src=\"%v1%\" frameborder=\"0\"></iframe>");
            ArticleDto[] allArticles = new ArticleDto[1];
            IList<MacroInvocation> mis = ar.LocateMacrosInContent(a);
            Assert.AreEqual(2, mis.Count);
            Assert.AreEqual(17, mis[0].StartingCharIndex);
            Assert.AreEqual(79, mis[0].EndingCharIndex);
        }
示例#9
0
        public void EscapedArticleMacrosTest()
        {
            MarkdownArticleProcessor ar = new MarkdownArticleProcessor(getAttributeSet());
            ArticleDto a = ar.ParseArticleRawText(
            @"---
            Title:Xbox Controller Repair
            Date:2014-08-02
            Category:Electronics
            Tags:Gaming,Electronics
            ---
            ##The internals
            ![:youtube 800 600](https://www.youtube.com/embed/Di5AT4MI6BY)
            \![:noMatchMacro parm1]", "Some\\File.md");

            MacroInvocation mi = ar.LocateMacrosInContent(a)[0];
            MarkdownMacro mdm = new MarkdownMacro("youtube", "<iframe width=\"%p1%\" height=\"%p2%\" src=\"%v1%\" frameborder=\"0\"></iframe>");
            ArticleDto[] allArticles = new ArticleDto[1];
            allArticles[0] = a;

            IList<MacroInvocation> miList = MarkdownUtil.LocateMarkdownMacros(a.Content);

            Assert.AreEqual(1, miList.Count);
            Assert.AreEqual("youtube", miList[0].MacroName);
        }
示例#10
0
 public IList<MacroInvocation> LocateMacrosInContent(ArticleDto article)
 {
     return new List<MacroInvocation>();
 }
示例#11
0
 public void FinaliseArticleHtml(ArticleDto article)
 {
     article.Content =
     @"<html><heade><title>My Great Aticle</title></head><body><h1>My Article</h1>
     Some important text</body></html>";
 }
示例#12
0
        /// <summary>
        /// Top level function of the site compilation/conversion process
        /// </summary>
        public bool ConvertArticles()
        {
            List <ArticleDto>                     articles = new List <ArticleDto>();
            IList <ITemplateProcessor>            templateProcessors;
            List <TemplateDto>                    templates = new List <TemplateDto>();
            List <IVirtualArticleGeneratorLoader> virtualArticleGenLoaders = new List <IVirtualArticleGeneratorLoader>();
            List <IVirtualArticleGenerator>       articleGenerators        = new List <IVirtualArticleGenerator>();

            virtualArticleGenLoaders.Add(new XslMarkdownArticleGeneratorLoader(validAttributes));
            virtualArticleGenLoaders.Add(new XslArticleGeneratorLoader(validAttributes));


            string[] articlePaths;

            templateProcessors = new List <ITemplateProcessor>();
            templateProcessors.Add(new MarkdownTemplateProcessor(validAttributes));


            if (validAttributes == null)
            {
                return(false);
            }

            //Load articles
            //At this point in time, we only have one type of article reader...
            IArticleProcessor articleProcessor = new MarkdownArticleProcessor(validAttributes);

            articlePaths = Directory.GetFiles(paths.ArticlesRootDir, "*" + articleProcessor.PrimaryFileExtension);
            foreach (string path in articlePaths)
            {
                string     relativePath = path.Substring(paths.ArticlesRootDir.Length);
                ArticleDto art          = articleProcessor.ParseArticleRawText(File.ReadAllText(path), relativePath);
                if (art != null)
                {
                    articles.Add(art);
                }
            }


            //Load templates
            foreach (ITemplateProcessor tp in templateProcessors)
            {
                string[] templatePaths = Directory.GetFiles(paths.TemplatesRootDir, "*" + tp.PrimaryFileExtension);
                foreach (string path in templatePaths)
                {
                    string      relativePath = path.Substring(paths.ArticlesRootDir.Length);
                    TemplateDto template     = tp.ParseTemplateRawText(File.ReadAllText(path), relativePath, Path.GetFileNameWithoutExtension(relativePath));
                    if (template != null)
                    {
                        template.TemplateProcessor = tp;
                        templates.Add(template);
                    }
                }
            }

            //Load virtual article generators
            if (!string.IsNullOrEmpty(paths.VirtualArticlesRootDir))
            {
                foreach (IVirtualArticleGeneratorLoader loader in virtualArticleGenLoaders)
                {
                    string[] generatorPaths = Directory.GetFiles(paths.VirtualArticlesRootDir, "*" + loader.PrimaryFileExtension);
                    foreach (string path in generatorPaths)
                    {
                        if (path.ToLower().EndsWith(loader.PrimaryFileExtension.ToLower()))
                        {
                            IVirtualArticleGenerator gen = loader.ParseGeneratorFromFile(path);
                            if (gen != null)
                            {
                                articleGenerators.Add(gen);
                            }
                        }
                    }
                }
            }

            applyOutputPaths(articles);

            createVirtualArticles(articles, articleGenerators);

            applyArticleTemplates(articles, templates);

            applyOutputPaths(articles);

            applyMacros(articles);

            transformArticles(articles);

            outputArticles(articles);

            return(true);
        }
示例#13
0
        /// <summary>
        /// Expands all macros found in an article's content. Will also expand macros added by macros.
        /// </summary>
        /// <param name="a">The article in question. Content will be updated.</param>
        /// <param name="articles">List of all known articles.</param>
        public void ProcessArticleMacros(ArticleDto a, IList <ArticleDto> articles)
        {
            IList <MacroInvocation> invokes = null;

            //This loop is just to allow an escape from an infinite macro expansion cycle
            for (int cycle = 0; cycle < 20; cycle++)
            {
                invokes = a.ArticleProcessorUsed.LocateMacrosInContent(a);
                invokes = new List <MacroInvocation>(invokes.OrderByDescending(x => x.StartingCharIndex));
                foreach (MacroInvocation mi in invokes)
                {
                    IMacro mac = null;
                    foreach (var provider in macroProviders)
                    {
                        mac = provider.TryLoadMacro(mi.MacroName);
                        if (mac != null)
                        {
                            break;
                        }
                    }
                    if (mac == null)
                    {
                        Logger.LogWarning("Macro " + mi.MacroName + " not found.");
                        continue;
                    }

                    //TODO: This is not the most efficient way to handle progressive replace. Should use stringbuilders.
                    string pre  = a.Content.Substring(0, mi.StartingCharIndex);
                    string post = a.Content.Substring(mi.EndingCharIndex);
                    a.Content = pre + mac.Expand(mi.Parameters, mi.Values, a, articles) + post;
                }
                if (invokes.Count == 0)
                {
                    break;
                }
            }

            if (invokes.Count > 0)
            {
                Logger.LogWarning("Article " + a.SourceFileRelativePath + " still had macros to expand after many passes. Check for macros recurively including each other.");
            }

            if (a.Template != null)
            {
                for (int cycle = 0; cycle < 20; cycle++)
                {
                    invokes = a.Template.TemplateProcessor.LocateMacrosInArticleTemplateContent(a);
                    invokes = new List <MacroInvocation> (invokes.OrderByDescending(x => x.StartingCharIndex));
                    foreach (MacroInvocation mi in invokes)
                    {
                        IMacro mac = null;
                        foreach (var provider in macroProviders)
                        {
                            mac = provider.TryLoadMacro(mi.MacroName);
                            if (mac != null)
                            {
                                break;
                            }
                        }
                        if (mac == null)
                        {
                            Logger.LogWarning("Macro " + mi.MacroName + " not found.");
                            continue;
                        }

                        //TODO: This is not the most efficient way to handle progressive replace. Should use stringbuilders.
                        string pre  = a.TemplateContent.Substring(0, mi.StartingCharIndex);
                        string post = a.TemplateContent.Substring(mi.EndingCharIndex);
                        a.TemplateContent = pre + mac.Expand(mi.Parameters, mi.Values, a, articles) + post;
                    }
                }
                if (invokes.Count > 0)
                {
                    Logger.LogWarning("Article template for " + a.SourceFileRelativePath + " still had macros to expand after many passes. Check for macros recurively including each other.");
                }
            }
        }
示例#14
0
        /// <summary>
        /// Expands all macros found in an article's content. Will also expand macros added by macros.
        /// </summary>
        /// <param name="a">The article in question. Content will be updated.</param>
        /// <param name="articles">List of all known articles.</param>
        public void ProcessArticleMacros(ArticleDto a, IList<ArticleDto> articles)
        {
            IList<MacroInvocation> invokes = null;

            //This loop is just to allow an escape from an infinite macro expansion cycle
            for(int cycle = 0; cycle < 20; cycle++)
            {
                invokes = a.ArticleProcessorUsed.LocateMacrosInContent(a);
                invokes = new List<MacroInvocation>(invokes.OrderByDescending(x => x.StartingCharIndex));
                foreach(MacroInvocation mi in invokes)
                {
                    IMacro mac = null;
                    foreach(var provider in macroProviders)
                    {
                        mac = provider.TryLoadMacro(mi.MacroName);
                        if (mac != null) break;
                    }
                    if(mac == null)
                    {
                        Logger.LogWarning("Macro " + mi.MacroName + " not found.");
                        continue;
                    }

                    //TODO: This is not the most efficient way to handle progressive replace. Should use stringbuilders.
                    string pre = a.Content.Substring(0, mi.StartingCharIndex);
                    string post = a.Content.Substring(mi.EndingCharIndex);
                    a.Content = pre + mac.Expand(mi.Parameters, mi.Values, a, articles) + post;
                }
                if (invokes.Count == 0) break;
            }

            if (invokes.Count > 0) Logger.LogWarning("Article " + a.SourceFileRelativePath + " still had macros to expand after many passes. Check for macros recurively including each other.");

            if(a.Template != null)
            {
                for(int cycle = 0; cycle < 20; cycle++)
                {
                    invokes = a.Template.TemplateProcessor.LocateMacrosInArticleTemplateContent(a);
                    invokes =  new List<MacroInvocation> (invokes.OrderByDescending(x => x.StartingCharIndex));
                    foreach (MacroInvocation mi in invokes)
                    {
                        IMacro mac = null;
                        foreach (var provider in macroProviders)
                        {
                            mac = provider.TryLoadMacro(mi.MacroName);
                            if (mac != null) break;
                        }
                        if (mac == null)
                        {
                            Logger.LogWarning("Macro " + mi.MacroName + " not found.");
                            continue;
                        }

                        //TODO: This is not the most efficient way to handle progressive replace. Should use stringbuilders.
                        string pre = a.TemplateContent.Substring(0, mi.StartingCharIndex);
                        string post = a.TemplateContent.Substring(mi.EndingCharIndex);
                        a.TemplateContent = pre + mac.Expand(mi.Parameters, mi.Values, a, articles) + post;
                    }
                }
                if (invokes.Count > 0) Logger.LogWarning("Article template for " + a.SourceFileRelativePath + " still had macros to expand after many passes. Check for macros recurively including each other.");
            }
        }
示例#15
0
 public IList <MacroInvocation> LocateMacrosInContent(ArticleDto article)
 {
     return(new List <MacroInvocation>());
 }
 public void BasicPathCreation()
 {
     ArticleDto article = new ArticleDto(@"Articles\MyArticle.md", new MockArticleProcessor());
     string calcPath = AttributeTranformations.CalculateArticlePath(article);
     Assert.AreEqual("Articles/MyArticle.html", calcPath);
 }
示例#17
0
        public void FinaliseArticleHtml(ArticleDto article)
        {
            article.Content =
                @"<html><heade><title>My Great Aticle</title></head><body><h1>My Article</h1>
Some important text</body></html>";
        }