コード例 #1
0
        private void GenerateSearchPage()
        {
            var activePath = new NavigatedPath();

            activePath.Push(this.Pages);
            var searchSimpleElement = new SimpleNavigationElement()
            {
                Name = "Search", Value = "Docnet_search.htm", IsIndexElement = false, ParentContainer = this.Pages
            };

            searchSimpleElement.ContentProducerFunc     = e => @"
					<h1 id=""search"">Search Results</h1>
					<p>
					<form id=""content_search"" action=""docnet_search.htm"">
						<span role= ""status"" aria-live=""polite"" class=""ui-helper-hidden-accessible""></span>
						<input name=""q"" id=""search-query"" type=""text"" class=""search_input search-query ui-autocomplete-input"" placeholder=""Search the Docs"" autocomplete=""off"" autofocus/>
					</form>
					</p>
					<div id=""search-results"">
					<p>Sorry, page not found.</p>
					</div>"                    ;
            searchSimpleElement.ExtraScriptProducerFunc = e => @"
	<script>var base_url = '.';</script>
	<script data-main=""js/search.js"" src=""js/require.js""></script>"    ;
            searchSimpleElement.GenerateOutput(this, activePath);
            activePath.Pop();
        }
コード例 #2
0
        /// <summary>
        /// The actual implementation of GenerateToCFragment. This is factored out to be able to re-use the fragment HTML product logic for the root index element
        /// which would otherwise be skipped as it's an index element.
        /// </summary>
        /// <param name="navigatedPath">The navigated path.</param>
        /// <param name="relativePathToRoot">The relative path to root.</param>
        /// <returns></returns>
        public string PerformGenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot)
        {
            // we can't navigate deeper from here. If we are the element being navigated to, we are the current and will have to emit any additional relative URLs too.
            bool isCurrent = navigatedPath.Contains(this);
            var  fragments = new List <string>();
            var  liClass   = "tocentry";
            var  aClass    = string.Empty;

            if (isCurrent)
            {
                liClass = "tocentry current";
                aClass  = "current";
            }
            fragments.Add(string.Format("<li{0}><a{1} href=\"{2}{3}\">{4}</a>",
                                        string.IsNullOrWhiteSpace(liClass) ? string.Empty : string.Format(" class=\"{0}\"", liClass),
                                        string.IsNullOrWhiteSpace(aClass) ? string.Empty : string.Format(" class=\"{0}\"", aClass),
                                        relativePathToRoot,
                                        HttpUtility.UrlPathEncode(this.TargetURL),
                                        this.Name));
            if (isCurrent && _relativeH2LinksOnPage.Any())
            {
                // generate relative links
                fragments.Add(string.Format("<ul class=\"{0}\">", this.ParentContainer.IsRoot ? "currentrelativeroot" : "currentrelative"));
                foreach (var p in _relativeH2LinksOnPage)
                {
                    fragments.Add(string.Format("<li class=\"tocentry\"><a href=\"#{0}\">{1}</a></li>", p.Item1, p.Item2));
                }
                fragments.Add("</ul>");
            }
            else
            {
                fragments.Add("</li>");
            }
            return(string.Join(Environment.NewLine, fragments.ToArray()));
        }
コード例 #3
0
ファイル: SearchIndexEntry.cs プロジェクト: zanzo420/DocNet
 public void Fill(string markDownFromFile, string targetURL, string title, NavigatedPath tocLocaton)
 {
     this.Location    = HttpUtility.UrlPathEncode(targetURL);
     this.Title       = title;
     this.BreadCrumbs = tocLocaton.CreateBreadCrumbsText(string.Empty).Replace("\"", "").Replace("'", "");
     RetrieveWords(markDownFromFile);
 }
コード例 #4
0
ファイル: NavigationLevel.cs プロジェクト: jango2015/DocNet
        /// <summary>
        /// Generates the ToC fragment for this element, which can either be a simple line or a full expanded menu.
        /// </summary>
        /// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param>
        /// <param name="relativePathToRoot">The relative path back to the URL root, e.g. ../.., so it can be used for links to elements in this path.</param>
        /// <returns></returns>
        public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot)
        {
            var fragments = new List <string>();

            if (!this.IsRoot)
            {
                fragments.Add("<li class=\"tocentry\">");
            }
            if (navigatedPath.Contains(this))
            {
                // we're expanded. If we're not root and on the top of the navigated path stack, our index page is the page we're currently generating the ToC for, so
                // we have to mark the entry as 'current'
                if (navigatedPath.Peek() == this && !this.IsRoot)
                {
                    fragments.Add("<ul class=\"current\">");
                }
                else
                {
                    fragments.Add("<ul>");
                }

                // first render the level header, which is the index element, if present or a label. The root always has an __index element otherwise we'd have stopped at load.
                var elementStartTag = "<li><span class=\"navigationgroup\"><i class=\"fa fa-caret-down\"></i> ";
                var indexElement    = this.IndexElement;
                if (indexElement == null)
                {
                    fragments.Add(string.Format("{0}{1}</span></li>", elementStartTag, this.Name));
                }
                else
                {
                    if (this.IsRoot)
                    {
                        fragments.Add(indexElement.PerformGenerateToCFragment(navigatedPath, relativePathToRoot));
                    }
                    else
                    {
                        fragments.Add(string.Format("{0}<a href=\"{1}{2}\">{3}</a></span></li>", elementStartTag, relativePathToRoot, HttpUtility.UrlPathEncode(indexElement.TargetURL),
                                                    this.Name));
                    }
                }
                // then the elements in the container. Index elements are skipped here.
                foreach (var element in this.Value)
                {
                    fragments.Add(element.GenerateToCFragment(navigatedPath, relativePathToRoot));
                }
                fragments.Add("</ul>");
            }
            else
            {
                // just a link
                fragments.Add(string.Format("<span class=\"navigationgroup\"><i class=\"fa fa-caret-right\"></i> <a href=\"{0}{1}\">{2}</a></span>",
                                            relativePathToRoot, HttpUtility.UrlPathEncode(this.TargetURL), this.Name));
            }
            if (!this.IsRoot)
            {
                fragments.Add("</li>");
            }
            return(string.Join(Environment.NewLine, fragments.ToArray()));
        }
コード例 #5
0
ファイル: NavigationLevel.cs プロジェクト: jango2015/DocNet
 /// <summary>
 /// Generates the output for this navigation element
 /// </summary>
 /// <param name="activeConfig">The active configuration to use for the output.</param>
 /// <param name="activePath">The active path navigated through the ToC to reach this element.</param>
 public override void GenerateOutput(Config activeConfig, NavigatedPath activePath)
 {
     activePath.Push(this);
     foreach (var element in this.Value)
     {
         element.GenerateOutput(activeConfig, activePath);
     }
     activePath.Pop();
 }
コード例 #6
0
        /// <summary>
        /// Generates the ToC fragment for this element, which can either be a simple line or a full expanded menu.
        /// </summary>
        /// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param>
        /// <param name="relativePathToRoot">The relative path back to the URL root, e.g. ../.., so it can be used for links to elements in this path.</param>
        /// <param name="navigationContext">The navigation context.</param>
        /// <returns></returns>
        public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext)
        {
            // index elements are rendered in the parent container.
            if (this.IsIndexElement)
            {
                return(string.Empty);
            }

            return(PerformGenerateToCFragment(navigatedPath, relativePathToRoot, navigationContext));
        }
コード例 #7
0
        /// <summary>
        /// Generates the output for this navigation element
        /// </summary>
        /// <param name="activeConfig">The active configuration to use for the output.</param>
        /// <param name="activePath">The active path navigated through the ToC to reach this element.</param>
        public override void GenerateOutput(Config activeConfig, NavigatedPath activePath)
        {
            activePath.Push(this);
            int i = 0;

            while (i < this.Value.Count)
            {
                var element = this.Value[i];
                element.GenerateOutput(activeConfig, activePath);
                i++;
            }
            activePath.Pop();
        }
コード例 #8
0
        /// <summary>
        /// The actual implementation of GenerateToCFragment. This is factored out to be able to re-use the fragment HTML product logic for the root index element
        /// which would otherwise be skipped as it's an index element.
        /// </summary>
        /// <param name="navigatedPath">The navigated path.</param>
        /// <param name="relativePathToRoot">The relative path to root.</param>
        /// <param name="navigationContext">The navigation context.</param>
        /// <returns></returns>
        public string PerformGenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext)
        {
            // we can't navigate deeper from here. If we are the element being navigated to, we are the current and will have to emit any additional relative URLs too.
            bool isCurrent = navigatedPath.Contains(this);
            var  fragments = new List <string>();
            var  liClass   = "tocentry";
            var  aClass    = string.Empty;

            if (isCurrent)
            {
                liClass = "tocentry current";
                aClass  = "current";
            }
            fragments.Add(string.Format("<li{0}><a{1} href=\"{2}{3}\">{4}</a>",
                                        string.IsNullOrWhiteSpace(liClass) ? string.Empty : string.Format(" class=\"{0}\"", liClass),
                                        string.IsNullOrWhiteSpace(aClass) ? string.Empty : string.Format(" class=\"{0}\"", aClass),
                                        relativePathToRoot,
                                        this.GetFinalTargetUrl(navigationContext),
                                        this.Name));
            if (isCurrent && _relativeLinksOnPage.Count > 0)
            {
                bool renderHeadings = _relativeLinksOnPage.SelectMany(x => x.Children).Any(x => x.Level > 1);
                if (!renderHeadings)
                {
                    // check if there are headings of a higher level than 1 present. If so, continue and render as usual
                    renderHeadings = _relativeLinksOnPage.Any(x => x.Level > 1);
                }

                if (renderHeadings)
                {
                    // generate relative links
                    fragments.Add("<ul class=\"currentrelative\">");

                    foreach (var heading in _relativeLinksOnPage)
                    {
                        var content = GenerateToCFragmentForHeading(heading, navigationContext);
                        if (!string.IsNullOrWhiteSpace(content))
                        {
                            fragments.Add(content);
                        }
                    }
                    fragments.Add("</ul>");
                }
            }
            else
            {
                fragments.Add("</li>");
            }
            return(string.Join(Environment.NewLine, fragments.ToArray()));
        }
コード例 #9
0
        internal void Generate404Page(NavigationContext navigationContext)
        {
            var simpleNavigationElement = new NotFoundNavigationElement
            {
                ParentContainer = Pages
            };

            var navigatedPath = new NavigatedPath();

            navigatedPath.Push(this.Pages);

            simpleNavigationElement.GenerateOutput(this, navigatedPath, navigationContext);

            navigatedPath.Pop();
        }
コード例 #10
0
 /// <summary>
 /// Collects the search index entries. These are created from simple navigation elements found in this container, which aren't index element.
 /// </summary>
 /// <param name="collectedEntries">The collected entries.</param>
 /// <param name="activePath">The active path currently navigated.</param>
 /// <param name="navigationContext">The navigation context.</param>
 public override void CollectSearchIndexEntries(List <SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext)
 {
     activePath.Push(this);
     // simply convert ourselves into an entry if we're not an index
     if (!this.IsIndexElement)
     {
         var toAdd = new SearchIndexEntry();
         toAdd.Fill(this.MarkdownFromFile, this.GetTargetURL(navigationContext), this.Name, activePath);
         collectedEntries.Add(toAdd);
     }
     activePath.Pop();
 }
コード例 #11
0
ファイル: NavigationLevel.cs プロジェクト: jango2015/DocNet
 /// <summary>
 /// Collects the search index entries. These are created from simple navigation elements found in this container, which aren't index element.
 /// </summary>
 /// <param name="collectedEntries">The collected entries.</param>
 /// <param name="activePath">The active path currently navigated.</param>
 public override void CollectSearchIndexEntries(List <SearchIndexEntry> collectedEntries, NavigatedPath activePath)
 {
     activePath.Push(this);
     foreach (var element in this.Value)
     {
         element.CollectSearchIndexEntries(collectedEntries, activePath);
     }
     activePath.Pop();
 }
コード例 #12
0
 public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext)
 {
     // Skip
     return(string.Empty);
 }
コード例 #13
0
 /// <summary>
 /// Collects the search index entries. These are created from simple navigation elements found in this container, which aren't index element.
 /// </summary>
 /// <param name="collectedEntries">The collected entries.</param>
 /// <param name="activePath">The active path currently navigated.</param>
 /// <param name="navigationContext">The navigation context.</param>
 public abstract void CollectSearchIndexEntries(List <SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext);
コード例 #14
0
 /// <summary>
 /// Generates the ToC fragment for this element, which can either be a simple line or a full expanded menu.
 /// </summary>
 /// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param>
 /// <param name="relativePathToRoot">The relative path back to the URL root, e.g. ../.., so it can be used for links to elements in this path.</param>
 /// <param name="navigationContext">The navigation context.</param>
 /// <returns></returns>
 public abstract string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext);
コード例 #15
0
 /// <summary>
 /// Generates the output for this navigation element
 /// </summary>
 /// <param name="activeConfig">The active configuration to use for the output.</param>
 /// <param name="activePath">The active path navigated through the ToC to reach this element.</param>
 /// <param name="navigationContext">The navigation context.</param>
 public abstract void GenerateOutput(Config activeConfig, NavigatedPath activePath, NavigationContext navigationContext);
コード例 #16
0
 public override void CollectSearchIndexEntries(List <SearchIndexEntry> collectedEntries, NavigatedPath activePath, NavigationContext navigationContext)
 {
     // Skip
 }
コード例 #17
0
        /// <summary>
        /// Generates the output for this navigation element
        /// </summary>
        /// <param name="activeConfig">The active configuration to use for the output.</param>
        /// <param name="activePath">The active path navigated through the ToC to reach this element.</param>
        /// <param name="navigationContext">The navigation context.</param>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="System.IO.FileNotFoundException"></exception>
        public override void GenerateOutput(Config activeConfig, NavigatedPath activePath, NavigationContext navigationContext)
        {
            // if we're the __index element, we're not pushing ourselves on the path, as we're representing the container we're in, which is already on the path.
            if (!this.IsIndexElement)
            {
                activePath.Push(this);
            }
            _relativeLinksOnPage.Clear();
            var sourceFile      = Utils.MakeAbsolutePath(activeConfig.Source, this.Value);
            var destinationFile = Utils.MakeAbsolutePath(activeConfig.Destination, this.GetTargetURL(navigationContext));
            var sb      = new StringBuilder(activeConfig.PageTemplateContents.Length + 2048);
            var content = string.Empty;

            this.MarkdownFromFile = string.Empty;
            var relativePathToRoot = Utils.MakeRelativePathForUri(Path.GetDirectoryName(destinationFile), activeConfig.Destination);

            if (File.Exists(sourceFile))
            {
                this.MarkdownFromFile = File.ReadAllText(sourceFile, Encoding.UTF8);
                // Check if the content contains @@include tag
                content = Utils.IncludeProcessor(this.MarkdownFromFile, Utils.MakeAbsolutePath(activeConfig.Source, activeConfig.IncludeFolder));
                content = Utils.ConvertMarkdownToHtml(content, Path.GetDirectoryName(destinationFile), activeConfig.Destination, sourceFile, _relativeLinksOnPage, activeConfig.ConvertLocalLinks);
            }
            else
            {
                // if we're not the index element, the file is missing and potentially it's an error in the config page.
                // Otherwise we can simply assume we are a missing index page and we'll generate default markdown so the user has something to look at.
                if (this.IsIndexElement)
                {
                    // replace with default markdown snippet. This is the name of our container and links to the elements in that container as we are the index page that's not
                    // specified / existend.
                    var defaultMarkdown = new StringBuilder();
                    defaultMarkdown.AppendFormat("# {0}{1}{1}", this.ParentContainer.Name, Environment.NewLine);
                    defaultMarkdown.AppendFormat("Please select one of the topics in this section:{0}{0}", Environment.NewLine);
                    foreach (var sibling in this.ParentContainer.Value)
                    {
                        if (sibling == this)
                        {
                            continue;
                        }
                        defaultMarkdown.AppendFormat("* [{0}]({1}{2}){3}", sibling.Name, relativePathToRoot,
                                                     sibling.GetFinalTargetUrl(navigationContext), Environment.NewLine);
                    }
                    defaultMarkdown.Append(Environment.NewLine);
                    content = Utils.ConvertMarkdownToHtml(defaultMarkdown.ToString(), Path.GetDirectoryName(destinationFile), activeConfig.Destination, string.Empty, _relativeLinksOnPage, activeConfig.ConvertLocalLinks);
                }
                else
                {
                    // target not found. See if there's a content producer func to produce html for us. If not, we can only conclude an error in the config file.
                    if (this.ContentProducerFunc == null)
                    {
                        throw new FileNotFoundException(string.Format("The specified markdown file '{0}' couldn't be found. Aborting", sourceFile));
                    }
                    content = this.ContentProducerFunc(this, activeConfig, navigationContext);
                }
            }
            sb.Append(activeConfig.PageTemplateContents);
            sb.Replace("{{Name}}", activeConfig.Name);
            sb.Replace("{{Footer}}", activeConfig.Footer);
            sb.Replace("{{TopicTitle}}", this.Name);
            sb.Replace("{{Path}}", relativePathToRoot);
            sb.Replace("{{RelativeSourceFileName}}", Utils.MakeRelativePathForUri(activeConfig.Destination, sourceFile).TrimEnd('/'));
            sb.Replace("{{RelativeTargetFileName}}", Utils.MakeRelativePathForUri(activeConfig.Destination, destinationFile).TrimEnd('/'));
            sb.Replace("{{Breadcrumbs}}", activePath.CreateBreadCrumbsHTML(relativePathToRoot, navigationContext));
            sb.Replace("{{ToC}}", activePath.CreateToCHTML(relativePathToRoot, navigationContext));
            sb.Replace("{{ExtraScript}}", (this.ExtraScriptProducerFunc == null) ? string.Empty : this.ExtraScriptProducerFunc(this, activeConfig, navigationContext));

            // the last action has to be replacing the content marker, so markers in the content which we have in the template as well aren't replaced
            sb.Replace("{{Content}}", content);
            Utils.CreateFoldersIfRequired(destinationFile);
            File.WriteAllText(destinationFile, sb.ToString());
            if (!this.IsIndexElement)
            {
                activePath.Pop();
            }
        }
コード例 #18
0
ファイル: NavigationElement.cs プロジェクト: qidouhai/DocNet
 /// <summary>
 /// Generates the output for this navigation element
 /// </summary>
 /// <param name="activeConfig">The active configuration to use for the output.</param>
 /// <param name="activePath">The active path navigated through the ToC to reach this element.</param>
 /// <returns>true if everything went well, false otherwise</returns>
 public abstract void GenerateOutput(Config activeConfig, NavigatedPath activePath);