Exemplo n.º 1
0
 //Removes the front matter, if any, from the actual content of the file
 //and removes the extra empty lines at the beginning and the end
 private void RemoveFrontMatter()
 {
     _rawContent = SimpleYAMLParser.RemoveFrontMatterFromContent(_rawContent);
 }
Exemplo n.º 2
0
        /// <summary>
        /// Reads a template from cache if available. If not, reads it from disk.
        /// Substitutes the template fields such as {basefolder}, before caching the result
        /// </summary>
        /// <param name="filePath">Path to the template</param>
        /// <param name="ctx">The current request context (needed in in order to transform virtual paths)</param>
        /// <param name="isInclude">true to indicate that the current template is a fragment of other template, so that is excludes content and other fragments from processing</param>
        /// <returns>The text contents of the template</returns>
        /// <exception cref="System.Security.SecurityException">Thrown if the app has no read access to the requested file</exception>
        /// <exception cref="System.IO.FileNotFoundException">Thrown when the requested file does not exist</exception>
        private static string ReadTemplate(string templateVirtualPath, HttpContext ctx, List <string> cacheDependencies, List <string> graph = null, bool isInclude = false)
        {
            string templatePath  = ctx.Server.MapPath(templateVirtualPath);
            string cachedContent = HttpRuntime.Cache[templatePath] as string;   //Templates are always cached for performance reasons (no switch/parameter to disable it)

            if (string.IsNullOrEmpty(cachedContent))
            {
                //Check for circular references
                if (graph != null)
                {
                    //Check if current file is already on the graph
                    //if it is, then we have a circular reference
                    if (graph.Contains(templatePath))
                    {
                        throw new CircularReferenceException(String.Format("Template not valid!\nThe file '{0}' is a circular reference: {1}", templateVirtualPath, String.Join(" >\n ", graph.ToArray())));
                    }
                    graph.Add(templatePath);    //Add current include to the graph to track circular references
                }

                var templateContents = IOHelper.ReadTextFromFile(templatePath);  //Read template contents from disk

                //Add current file as cache dependency (the read process will add the fragments if needed)
                if (!cacheDependencies.Contains(templatePath))
                {
                    cacheDependencies.Add(templatePath);
                }

                string phValue;    //The value to substitute the placeholder

                /////////////////////////////////////////////
                // Process template inheritance (if any)
                /////////////////////////////////////////////

                //Check if there's Front-Matter or not
                string strFM = SimpleYAMLParser.GetFrontMatterFromContent(templateContents);
                //If FM is present
                if (strFM != SimpleYAMLParser.EMPTY_FRONT_MATTER)
                {
                    //Remove the FM
                    templateContents = SimpleYAMLParser.RemoveFrontMatterFromContent(templateContents);
                    //get the Layout field from the current template's FM
                    SimpleYAMLParser yaml   = new SimpleYAMLParser(strFM);
                    string           layout = yaml["layout"];
                    //If there's a layout specified, use it as the base layout for the current template
                    if (!string.IsNullOrEmpty(layout))
                    {
                        //Process the layout
                        string parentTemplateVPath   = VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(templateVirtualPath)) + "/" + layout;;
                        string parentTemplateContent = ReadTemplate(parentTemplateVPath, ctx, cacheDependencies, graph);
                        //Substitute the content field in the parent layout, with the current template's content
                        templateContents = TemplatingHelper.ReplacePlaceHolder(parentTemplateContent, "content", templateContents);
                    }
                }


                ////////////////////////////////////////////
                //Search for includes in the current file and substitute them, before substituting any other placeholder
                ////////////////////////////////////////////
                string[] includes = TemplatingHelper.GetAllPlaceHolderNames(templateContents, "", FILE_INCLUDES_PREFIX);

                //Substitute includes with their contents
                foreach (string include in includes)
                {
                    string includeFileName = VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(templateVirtualPath)) + "/" + include.Substring(FILE_INCLUDES_PREFIX.Length);  //The current template file folder + the include filename
                    try
                    {
                        //Initialize graph to detect circular references
                        List <string> newGraph;
                        if (graph == null)
                        {
                            newGraph = new List <string>()
                            {
                                templatePath
                            };
                        }
                        else
                        {
                            newGraph = graph;
                        }
                        phValue = ReadTemplate(includeFileName, ctx, cacheDependencies, newGraph, true);    //Insert the raw contents of the include (no processing!)
                    }
                    catch (CircularReferenceException crex)
                    {
                        throw crex;
                    }
                    catch   //If it fails, simply do nothing and show the error
                    {
                        phValue = String.Format("<!-- Include file '{0}' not found  -->", includeFileName);
                    }
                    templateContents = TemplatingHelper.ReplacePlaceHolder(templateContents, include, phValue);
                }


                if (!isInclude)
                {
                    //After inserting all the "includes", check if there's a content placeholder present (mandatory)
                    if (!TemplatingHelper.IsPlaceHolderPresent(templateContents, "content"))
                    {
                        throw new Exception("Invalid template '" + templateVirtualPath + "': The " + TemplatingHelper.GetPlaceholderName("content") + " placeholder must be present!");
                    }

                    //////////////////////////////
                    //Replace template-specific fields
                    //////////////////////////////
                    //Legacy "basefolder" placeholder (now "~/" it's recommended)
                    templateContents = TemplatingHelper.ReplacePlaceHolder(templateContents, "basefolder", "~/");
                    //Template base folder
                    templateContents = TemplatingHelper.ReplacePlaceHolder(templateContents, "templatebasefolder",
                                                                           VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(VirtualPathUtility.ToAbsolute(templateVirtualPath))));

                    //Transform virtual paths into absolute to the root paths (This is done only once per file if cached)
                    templateContents = WebHelper.TransformVirtualPaths(templateContents);

                    //If it's the main file, add result to cache with dependency on the file(s)
                    //Templates are cached ALWAYS, and this is not dependent on the caching parameter (that one is only for MarkDown or MDH files)
                    HttpRuntime.Cache.Insert(templatePath, templateContents, new CacheDependency(cacheDependencies.ToArray()));
                    //Keep a list of template's dependencies to reuse when not reading from cache
                    ctx.Application[templatePath] = cacheDependencies;
                }

                return(templateContents); //Return content
            }
            else
            {
                //Get dependencies for this template
                cacheDependencies.AddRange(ctx.Application[templatePath] as List <string>);
                return(cachedContent);   //Return directly from cache
            }
        }