Esempio n. 1
0
        // Group: Functions
        // __________________________________________________________________________


        /* Constructor: JSSummaryData
         */
        public JSSummaryData(HTMLTopicPage topicPage)
        {
            this.topicPage = topicPage;

            output       = null;
            fileTitle    = null;
            fileHashPath = null;
            topics       = null;

            usedLanguages    = new List <Language>();
            usedCommentTypes = new List <CommentType>();

            HTML.Context context = new HTML.Context(HTMLBuilder, topicPage);
            tooltipBuilder       = new HTML.Components.Tooltip(context);
            formattedTextBuilder = new HTML.Components.FormattedText(context);
        }
Esempio n. 2
0
        /* Function: BuildSummaryToolTips
         */
        protected void BuildSummaryToolTips()
        {
            if (!EngineInstance.Config.ShrinkFiles)
            {
                output.AppendLine();
                output.Append("   ");
            }

            bool first = true;

            HTML.Context context = new HTML.Context(HTMLBuilder);

            for (int topicIndex = 0; topicIndex < topics.Count; topicIndex++)
            {
                Topic topic = topics[topicIndex];

                if (topic.IsEmbedded == false)
                {
                    string toolTipHTML = tooltipBuilder.BuildToolTip(topic, context, links);

                    if (toolTipHTML != null)
                    {
                        if (!first)
                        {
                            output.Append(',');

                            if (!EngineInstance.Config.ShrinkFiles)
                            {
                                output.AppendLine();
                                output.Append("   ");
                            }
                        }

                        output.Append(topic.TopicID);
                        output.Append(":\"");
                        output.StringEscapeAndAppend(toolTipHTML);
                        output.Append('"');

                        first = false;
                    }
                }
            }
        }
Esempio n. 3
0
        /* Function: Build
         *
         * Builds the page and its supporting JSON files.  Returns whether there was any content.  It will also return false
         * if it was interrupted by the <CancelDelegate>.
         *
         * If the <CodeDB.Accessor> doesn't have a lock, this function will automatically acquire and release a read-only lock.
         * This is the preferred way of using this function as the lock will only be held during the data querying stage and will be
         * released before writing output to disk.  If it already has a lock it will use it and not release it.
         */
        public bool Build(CodeDB.Accessor accessor, CancelDelegate cancelDelegate)
        {
            bool releaseDBLock = false;

            if (accessor.LockHeld == CodeDB.Accessor.LockType.None)
            {
                accessor.GetReadOnlyLock();
                releaseDBLock = true;
            }

            try
            {
                // DEPENDENCY: HTMLTopicPages.Class assumes that this function will call a database function before using any path
                // properties.

                List <Topic> topics = GetTopics(accessor, cancelDelegate) ?? new List <Topic>();

                if (topics.Count == 0 || cancelDelegate())
                {
                    return(false);
                }

                List <Link> links = GetLinks(accessor, cancelDelegate) ?? new List <Link>();

                if (cancelDelegate())
                {
                    return(false);
                }


                // Find all the classes that are defined in this page, since we have to do additional lookups for class prototypes.

                IDObjects.NumberSet classIDsDefined = new IDObjects.NumberSet();

                foreach (var topic in topics)
                {
                    if (topic.DefinesClass)
                    {
                        classIDsDefined.Add(topic.ClassID);
                    }
                }

                if (cancelDelegate())
                {
                    return(false);
                }


                // We need the class parent links of all the classes defined on this page so the class prototypes can show the parents.
                // If this is a class page then we can skip this step since all the links should already be included.  However, for any
                // other type of page this may not be the case.  A source file page would return all the links in that file, but the class
                // may be defined across multiple files and we need the class parent links in all of them.  In this case we need to look
                // up the class parent links separately by class ID.

                if ((this is HTMLTopicPages.Class) == false && classIDsDefined.IsEmpty == false)
                {
                    List <Link> classParentLinks = accessor.GetClassParentLinksInClasses(classIDsDefined, cancelDelegate);

                    if (classParentLinks != null && classParentLinks.Count > 0)
                    {
                        links.AddRange(classParentLinks);
                    }
                }

                if (cancelDelegate())
                {
                    return(false);
                }


                // Now we need to find the children of all the classes defined on this page.  Get the class parent links that resolve to
                // any of the defined classes, but keep them separate for now.

                List <Link> childLinks = null;

                if (classIDsDefined.IsEmpty == false)
                {
                    childLinks = accessor.GetClassParentLinksToClasses(classIDsDefined, cancelDelegate);
                }

                if (cancelDelegate())
                {
                    return(false);
                }


                // Get link targets for everything but the children, since they would just resolve to classes already in this file.

                IDObjects.NumberSet linkTargetIDs = new IDObjects.NumberSet();

                foreach (Link link in links)
                {
                    if (link.IsResolved)
                    {
                        linkTargetIDs.Add(link.TargetTopicID);
                    }
                }

                List <Topic> linkTargets = accessor.GetTopicsByID(linkTargetIDs, cancelDelegate) ?? new List <Topic>();

                if (cancelDelegate())
                {
                    return(false);
                }


                // Now get targets for the children.

                List <Topic> childTargets = null;

                if (childLinks != null && childLinks.Count > 0)
                {
                    IDObjects.NumberSet childClassIDs = new IDObjects.NumberSet();

                    foreach (var childLink in childLinks)
                    {
                        childClassIDs.Add(childLink.ClassID);
                    }

                    childTargets = accessor.GetBestClassDefinitionTopics(childClassIDs, cancelDelegate);
                }

                if (cancelDelegate())
                {
                    return(false);
                }


                // We can merge the child links and targets into the main lists now.

                if (childLinks != null)
                {
                    links.AddRange(childLinks);
                }

                if (childTargets != null)
                {
                    linkTargets.AddRange(childTargets);
                }

                if (cancelDelegate())
                {
                    return(false);
                }


                // Now we need to find any Natural Docs links appearing inside the summaries of link targets.  The tooltips
                // that will be generated for them include their summaries, and even though we don't generate HTML links
                // inside tooltips, how and if they're resolved affects the appearance of Natural Docs links.  We need to know
                // whether to include the original text with angle brackets, the text without angle brackets if it's resolved, or
                // only part of the text if it's a resolved named link.

                // Links don't store which topic they appear in but they do store the file, so gather the file IDs of the link
                // targets that have Natural Docs links in the summaries and get all the links in those files.

                // Links also store which class they appear in, so why not do this by class instead of by file?  Because a
                // link could be to something global, and the global scope could potentially have a whole hell of a lot of
                // content, depending on the project and language.  While there can also be some really long files, the
                // chances of that are smaller so we stick with doing this by file.

                IDObjects.NumberSet summaryLinkFileIDs = new IDObjects.NumberSet();

                foreach (Topic linkTarget in linkTargets)
                {
                    if (linkTarget.Summary != null && linkTarget.Summary.IndexOf("<link type=\"naturaldocs\"") != -1)
                    {
                        summaryLinkFileIDs.Add(linkTarget.FileID);
                    }
                }

                List <Link> summaryLinks = null;

                if (!summaryLinkFileIDs.IsEmpty)
                {
                    summaryLinks = accessor.GetNaturalDocsLinksInFiles(summaryLinkFileIDs, cancelDelegate);
                }

                if (cancelDelegate())
                {
                    return(false);
                }


                // Finally done with the database.

                if (releaseDBLock)
                {
                    accessor.ReleaseLock();
                    releaseDBLock = false;
                }


                try
                {
                    // Build the HTML for the list of topics

                    StringBuilder html = new StringBuilder("\r\n\r\n");

                    HTML.Context            context        = new HTML.Context(HTMLBuilder, this);
                    HTML.Components.Topic   topicBuilder   = new HTML.Components.Topic(context);
                    HTML.Components.Tooltip tooltipBuilder = new HTML.Components.Tooltip(context);

                    // We don't put embedded topics in the output, so we need to find the last non-embedded one to make
                    // sure that the "last" CSS tag is correctly applied.
                    int lastNonEmbeddedTopic = topics.Count - 1;
                    while (lastNonEmbeddedTopic > 0 && topics[lastNonEmbeddedTopic].IsEmbedded == true)
                    {
                        lastNonEmbeddedTopic--;
                    }

                    for (int i = 0; i <= lastNonEmbeddedTopic; i++)
                    {
                        string extraClass = null;

                        if (i == 0)
                        {
                            extraClass = "first";
                        }
                        else if (i == lastNonEmbeddedTopic)
                        {
                            extraClass = "last";
                        }

                        if (topics[i].IsEmbedded == false)
                        {
                            topicBuilder.AppendTopic(topics[i], context, links, linkTargets, html, topics, i + 1, extraClass);
                            html.Append("\r\n\r\n");
                        }
                    }


                    // Build the full HTML file

                    htmlBuilder.BuildFile(OutputFile, PageTitle, html.ToString(), Builders.HTML.PageType.Content);


                    // Build the tooltips file

                    using (System.IO.StreamWriter file = htmlBuilder.CreateTextFileAndPath(ToolTipsFile))
                    {
                        file.Write("NDContentPage.OnToolTipsLoaded({");

                        if (!EngineInstance.Config.ShrinkFiles)
                        {
                            file.WriteLine();
                        }

                        for (int i = 0; i < linkTargets.Count; i++)
                        {
                            Topic  topic       = linkTargets[i];
                            string toolTipHTML = tooltipBuilder.BuildToolTip(topic, context, summaryLinks);

                            if (toolTipHTML != null)
                            {
                                if (!EngineInstance.Config.ShrinkFiles)
                                {
                                    file.Write("   ");
                                }

                                file.Write(topic.TopicID);
                                file.Write(":\"");
                                file.Write(toolTipHTML.StringEscape());
                                file.Write('"');

                                if (i != linkTargets.Count - 1)
                                {
                                    file.Write(',');
                                }

                                if (!EngineInstance.Config.ShrinkFiles)
                                {
                                    file.WriteLine();
                                }
                            }
                        }

                        if (!EngineInstance.Config.ShrinkFiles)
                        {
                            file.Write("   ");
                        }

                        file.Write("});");
                    }


                    // Build summary and summary tooltips files

                    JSSummaryData summaryBuilder = new JSSummaryData(this);
                    summaryBuilder.Build(topics, links, PageTitle, OutputFileHashPath, SummaryFile, SummaryToolTipsFile);

                    return(true);
                }
                catch (Exception e)
                {
                    try
                    { e.AddNaturalDocsTask("Building File: " + OutputFile); }
                    catch
                    {  }

                    throw;
                }
            }

            finally
            {
                if (releaseDBLock)
                {
                    accessor.ReleaseLock();
                }
            }
        }