/* Function: Build * Generates JSON files for all entries in the menu. It returns a <StringTable> mapping the file type strings ("files", * "classes", etc.) to a <IDObjects.NumberSet> representing all the files that were generated. So "files.js", "files2.js", * and "files3.js" would map to "files" -> {1-3}. */ public StringTable <IDObjects.NumberSet> Build() { try { // This will create multiple subdirectories if needed, and will not throw an exception if it already exists. System.IO.Directory.CreateDirectory(HTMLBuilder.Menu_DataFolder); } catch (Exception e) { throw new Exceptions.UserFriendly( Locale.Get("NaturalDocs.Engine", "Error.CouldNotCreateOutputFolder(name, exception)", HTMLBuilder.Menu_DataFolder, e.Message) ); } // Build menu files StringTable <IDObjects.NumberSet> outputFiles = new StringTable <IDObjects.NumberSet>(); if (RootFileMenu != null) { GenerateJSON(RootFileMenu); SegmentMenu(RootFileMenu, "files", ref outputFiles); BuildOutput(RootFileMenu); } if (RootClassMenu != null) { GenerateJSON(RootClassMenu); SegmentMenu(RootClassMenu, "classes", ref outputFiles); BuildOutput(RootClassMenu); } if (RootDatabaseMenu != null) { GenerateJSON(RootDatabaseMenu); SegmentMenu(RootDatabaseMenu, "database", ref outputFiles); BuildOutput(RootDatabaseMenu); } // Build tab information file StringBuilder tabInformation = new StringBuilder("NDMenu.OnTabsLoaded(["); if (!EngineInstance.Config.ShrinkFiles) { tabInformation.Append('\n'); } List <MenuEntries.Base.Container> tabContainers = new List <MenuEntries.Base.Container>(); List <string> tabTypes = new List <string>(); // DEPENDENCY: tabTypes must use the same strings as the NDLocation JavaScript class. // DEPENDENCY: tabTypes must use strings safe for including in CSS names. if (RootFileMenu != null) { tabContainers.Add(RootFileMenu); tabTypes.Add("File"); } if (RootClassMenu != null) { tabContainers.Add(RootClassMenu); tabTypes.Add("Class"); } if (RootDatabaseMenu != null) { tabContainers.Add(RootDatabaseMenu); tabTypes.Add("Database"); } for (int i = 0; i < tabContainers.Count; i++) { ContainerExtraData extraData = (ContainerExtraData)tabContainers[i].ExtraData; if (!EngineInstance.Config.ShrinkFiles) { tabInformation.Append(' ', IndentSpaces); } tabInformation.Append("[\""); tabInformation.Append(tabTypes[i]); tabInformation.Append("\","); if (tabContainers[i].CondensedTitles == null) { tabInformation.Append('"'); tabInformation.StringEscapeAndAppend(tabContainers[i].Title.ToHTML()); tabInformation.Append('"'); } else { tabInformation.Append("[\""); tabInformation.StringEscapeAndAppend(tabContainers[i].Title.ToHTML()); tabInformation.Append('"'); foreach (var condensedTitle in tabContainers[i].CondensedTitles) { tabInformation.Append(",\""); tabInformation.StringEscapeAndAppend(condensedTitle.ToHTML()); tabInformation.Append('"'); } tabInformation.Append(']'); } tabInformation.Append(','); if (extraData.HashPath != null) { tabInformation.Append('"'); tabInformation.StringEscapeAndAppend(extraData.HashPath); tabInformation.Append('"'); } // Otherwise leave an empty spot before the comma. We don't have to write out "undefined". tabInformation.Append(",\""); tabInformation.StringEscapeAndAppend(extraData.DataFileName); tabInformation.Append("\"]"); if (i < tabContainers.Count - 1) { tabInformation.Append(','); } if (!EngineInstance.Config.ShrinkFiles) { tabInformation.Append('\n'); } } if (!EngineInstance.Config.ShrinkFiles) { tabInformation.Append(' ', IndentSpaces); } tabInformation.Append("]);"); System.IO.File.WriteAllText(HTMLBuilder.Menu_DataFile("tabs", 1), tabInformation.ToString()); return(outputFiles); }