Example #1
0
 private static void TraverseIndexedDocuments(IndexedDocument doc, List <IndexedDocument> ordered)
 {
     ordered.Add(doc);
     foreach (var next in doc.Next)
     {
         TraverseIndexedDocuments(next, ordered);
     }
 }
Example #2
0
        private static List <IndexedDocument> OrderIndexedDocuments(List <IndexedDocument> indexedDocs)
        {
            Dictionary <string, IndexedDocument> index = new Dictionary <string, IndexedDocument>(indexedDocs.Count);
            IndexedDocument root = null;

            foreach (IndexedDocument doc in indexedDocs)
            {
                IndexedDocument existingDoc;
                if (index.TryGetValue(doc.Id, out existingDoc))
                {
                    throw new ApplicationException(String.Format("Document: {0} and document: {1} generate same identifier. Change one of the file names or trying cleaning and building again if you recently renamed a file.", existingDoc.RelativeOutputPath, doc.RelativeOutputPath));
                }

                index.Add(doc.Id, doc);
            }

            foreach (IndexedDocument doc in indexedDocs)
            {
                if (String.IsNullOrEmpty(doc.AfterId))
                {
                    if (null != root)
                    {
                        throw new ApplicationException(String.Format("Found multiple root documents at: {0} and {1}. Only one document can be the root 'index' file.", root.RelativeOutputPath, doc.RelativeOutputPath));
                    }

                    root = doc;
                }
                else
                {
                    IndexedDocument beforeDoc;
                    if (!index.TryGetValue(doc.AfterId, out beforeDoc))
                    {
                        throw new ArgumentException(String.Format("Error in document: {0} cannot find matching document for metadata: after={1}", doc.RelativeOutputPath, doc.OriginalAfter));
                    }

                    beforeDoc.AddAfter(doc);
                }
            }

            if (null == root)
            {
                throw new ApplicationException("Cannot find root document. There must be one and only one document named 'index' in the root that is not after any other document.");
            }

            List <IndexedDocument> ordered = new List <IndexedDocument>(indexedDocs.Count);

            TraverseIndexedDocuments(root, ordered);

            return(ordered);
        }
Example #3
0
        /// <summary>
        /// Run the application.
        /// </summary>
        /// <param name="commandLine">The command line arguments.</param>
        /// <returns>The error code for the application.</returns>
        private int Run(CommandLine commandLine)
        {
            Uri outputUri = new Uri(commandLine.OutputFolder);
            List <IndexedDocument> indexedDocs = new List <IndexedDocument>();

            // Build up a list of directories to ignore when processing documents.
            var ignored = commandLine.Ignored.Select(dir => Path.Combine(commandLine.InputFolder, dir));

            foreach (string documentPath in Directory.GetFiles(commandLine.InputFolder, "*.*", SearchOption.AllDirectories))
            {
                // Skip processing if the document path is ignored.
                if (ignored.Any(str => documentPath.StartsWith(str, StringComparison.OrdinalIgnoreCase)))
                {
                    break;
                }

                Document doc = Document.Create(documentPath, commandLine.InputFolder);
                string   documentOutputPath = Path.Combine(commandLine.OutputFolder, doc.RelativeOutputPath);
                string   content            = doc.Content;

                List <string> defines = new List <string>();
                defines.Add(String.Concat("content=", content)); // ensure "content" variable is first so it always wins.

                string layout;
                if (doc.Meta.TryGetValue("layout", out layout))
                {
                    string layoutContent;
                    if (!this.TryLoadLayout(commandLine.LayoutsFolder, layout, out layoutContent))
                    {
                        throw new ArgumentException(String.Format("Error could not find layout: {0} in the layout folder: {1} while processing document: {2}", layout, commandLine.LayoutsFolder, doc.RelativePath));
                    }

                    content = layoutContent; // replace the content with the layout, hopefully the layout has "{{content}}" in it somewhere.
                }

                defines.AddRange(commandLine.Variables);                                             // command-line variables trump document meta.
                defines.AddRange(doc.Meta.Select(meta => String.Concat(meta.Key, "=", meta.Value))); // document meta is last.

                content = SubstituteVariables(defines, content);

                content = DocCompiler.FixRelativePaths(content, new Uri(documentOutputPath), outputUri);

                var indexedDoc = new IndexedDocument(doc, commandLine.OutputFolder);
                indexedDocs.Add(indexedDoc);

                if (!indexedDoc.ChmIgnored)
                {
                    Output(content, documentOutputPath);
                }
            }

            List <IndexedDocument> ordered = OrderIndexedDocuments(indexedDocs);

            // Useful context when debugging.
            //DumpIndex(rootDoc);
            //Console.WriteLine("------");
            //DumpOrderedIndexedDocuments(ordered);

            if (!String.IsNullOrEmpty(commandLine.AppendMarkdownTableOfContentsFile))
            {
                AppendMarkdownTableOfContents(ordered, commandLine.AppendMarkdownTableOfContentsFile, commandLine.IgnoreXsdSimpleTypeInTableOfContents);
            }

            if (!String.IsNullOrEmpty(commandLine.HtmlHelpProjectFile))
            {
                GenerateHtmlHelpProject(ordered, commandLine.HtmlHelpProjectFile, commandLine.OutputFolder);
            }

            return(0);
        }
Example #4
0
        private void GenerateHtmlHelpProject(List <IndexedDocument> ordered, string projectFile, string outputFolder)
        {
            Uri    projectUri   = new Uri(Path.GetDirectoryName(Path.GetFullPath(projectFile)) + Path.DirectorySeparatorChar);
            Uri    outputUri    = new Uri(Path.GetFullPath(outputFolder + Path.DirectorySeparatorChar));
            string relativePath = projectUri.MakeRelativeUri(outputUri).ToString();

            IndexedDocument root = ordered.Where(d => d.ChmDefault).FirstOrDefault();

            if (null == root)
            {
                throw new ApplicationException("Cannot find default document. There must be one and only one document with meta 'chm: default' in set of documents compiled into a .chm.");
            }

            string chmFile   = Path.ChangeExtension(projectFile, ".chm");
            string indexFile = Path.ChangeExtension(projectFile, ".hhk");
            string tocFile   = Path.ChangeExtension(projectFile, ".hhc");
            string logFile   = Path.ChangeExtension(projectFile, ".log");

            // create the project file
            using (StreamWriter sw = File.CreateText(projectFile))
            {
                sw.WriteLine("[OPTIONS]");
                sw.WriteLine("Compatibility=1.1 or later");
                sw.WriteLine(String.Format("Compiled file={0}", chmFile));
                sw.WriteLine("Contents file={0}", tocFile);
                sw.WriteLine("Index file={0}", indexFile);
                sw.WriteLine("Default Window=Main");
                sw.WriteLine(String.Format("Default topic={0}", Path.Combine(relativePath, root.RelativeOutputPath)));
                sw.WriteLine("Display compile progress=No");
                sw.WriteLine("Error log file={0}", logFile);
                sw.WriteLine("Full-text search=Yes");
                sw.WriteLine("Language=0x409 English (United States)");
                sw.WriteLine(String.Format("Title={0}", root.TitleHtmlSafe));
                sw.WriteLine("");
                sw.WriteLine("[WINDOWS]");
                sw.WriteLine("Main=,\"{0}\",\"{1}\",\"{2}\",\"{2}\",,,,,0x63520,,0x384e,,,,,,,,0", tocFile, indexFile, Path.Combine(relativePath, root.RelativeOutputPath));
            }

            // create the index file
            using (StreamWriter sw = File.CreateText(indexFile))
            {
                sw.WriteLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
                sw.WriteLine("<HTML>");
                sw.WriteLine("<HEAD>");
                sw.WriteLine("<META NAME=\"GENERATOR\" CONTENT=\"WiX Toolset DocCompiler\"/>");
                sw.WriteLine("</HEAD>");
                sw.WriteLine("<BODY>");
                sw.WriteLine("<OBJECT TYPE=\"text/site properties\">");
                sw.WriteLine("\t<PARAM NAME=\"FrameName\" VALUE=\"TEXT\"/>");
                sw.WriteLine("</OBJECT>");
                sw.WriteLine("<UL>");

                foreach (var doc in ordered)
                {
                    if (doc.ChmIgnored)
                    {
                        continue;
                    }

                    sw.WriteLine("\t<LI> <OBJECT type=\"text/sitemap\">");
                    sw.WriteLine(String.Format("\t\t<param name=\"Keyword\" value=\"{0}\">", doc.TitleHtmlSafe));
                    sw.WriteLine(String.Format("\t\t<param name=\"Name\" value=\"{0}\">", doc.TitleHtmlSafe));
                    sw.WriteLine(String.Format("\t\t<param name=\"Local\" value=\"{0}\">", Path.Combine(relativePath, doc.RelativeOutputPath)));
                    sw.WriteLine("\t\t</OBJECT>");
                }

                sw.WriteLine("</UL>");
                sw.WriteLine("</BODY>");
                sw.WriteLine("</HTML>");
            }

            // create the table of contents file
            using (StreamWriter sw = File.CreateText(tocFile))
            {
                sw.WriteLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
                sw.WriteLine("<HTML>");
                sw.WriteLine("<HEAD>");
                sw.WriteLine("<meta name=\"GENERATOR\" content=\"Microsoft&reg; HTML Help Workshop 4.1\">");
                sw.WriteLine("<!-- Sitemap 1.0 -->");
                sw.WriteLine("</HEAD><BODY>");
                sw.WriteLine("<OBJECT type=\"text/site properties\">");
                sw.WriteLine("\t<param name=\"ImageType\" value=\"Folder\">");
                sw.WriteLine("</OBJECT>");
                sw.WriteLine("<UL>");

                int depth = root.Depth;
                foreach (var doc in ordered)
                {
                    if (doc.ChmIgnored)
                    {
                        continue;
                    }

                    while (depth < doc.Depth)
                    {
                        sw.WriteLine("<UL>");
                        ++depth;
                    }

                    while (depth > doc.Depth)
                    {
                        sw.WriteLine("</UL>");
                        --depth;
                    }

                    sw.WriteLine("\t<LI> <OBJECT type=\"text/sitemap\">");
                    sw.WriteLine(String.Format("\t\t<param name=\"Name\" value=\"{0}\">", doc.TitleHtmlSafe));
                    sw.WriteLine(String.Format("\t\t<param name=\"Local\" value=\"{0}\">", Path.Combine(relativePath, doc.RelativeOutputPath)));
                    sw.WriteLine("\t\t</OBJECT>");
                }

                while (depth > root.Depth)
                {
                    sw.WriteLine("</UL>");
                    --depth;
                }

                sw.WriteLine("</UL>");
                sw.WriteLine("</BODY></HTML>");
            }
        }