/// <summary> /// Creates tab header from tab. /// </summary> private void CreateTabHeader(Tab tab, int index = -1, object itemData = null) { // check if the tab has a custom tab header var tabHeader = tab.Find <TabHeader>(false); if (tabHeader == null) { // create default TabHeader tabHeader = ViewData.CreateView <TabHeader>(TabHeaderList.Content, tab.Parent, null, Theme, String.Empty, Style); tabHeader.ParentTab = tab; if (index >= 0) { tabHeader.transform.SetSiblingIndex(index + 1); } if (itemData != null) { SetItemData(tabHeader, itemData); } // initialize tab header tabHeader.InitializeViews(); } else { // move tab header to list tabHeader.MoveTo(TabHeaderList.Content, index >= 0 ? index + 1 : -1); TabHeaderList.QueueChangeHandler("LayoutChanged"); } // make sure tab bindings are propagated to header tab.PropagateBindings(); TabHeaderList.UpdatePresentedListItems(); }
/// <summary> /// Generates XSD schema from view type data. /// </summary> public static void GenerateXsdSchema() { if (ViewPresenter.Instance == null) { Debug.LogError("[MarkLight] Unable to generate XSD schema. View presenter can't be found in scene. Make sure the view presenter is enabled."); return; } var sb = new StringBuilder(); sb.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); sb.AppendLine("<xs:schema id=\"MarkLight\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"MarkLight\" xmlns=\"MarkLight\" attributeFormDefault=\"unqualified\" elementFormDefault=\"qualified\">"); // create temporary root view where instantiate each view to get info about view fields if (ViewPresenter.Instance.RootView == null) { ViewPresenter.Instance.RootView = ViewData.CreateView <View>(ViewPresenter.Instance, ViewPresenter.Instance).gameObject; } var layoutRoot = ViewPresenter.Instance.RootView.GetComponent <View>(); var temporaryRootView = ViewData.CreateView <View>(layoutRoot, layoutRoot); var enums = new HashSet <Type>(); Utils.SuppressLogging = true; // generate XSD schema based on view type data foreach (var viewType in ViewPresenter.Instance.ViewTypeDataList) { sb.AppendLine(); sb.AppendFormat(" <xs:element name=\"{0}\" type=\"{0}\" />{1}", viewType.ViewTypeName, Environment.NewLine); sb.AppendFormat(" <xs:complexType name=\"{0}\">{1}", viewType.ViewTypeName, Environment.NewLine); sb.AppendFormat(" <xs:sequence>{0}", Environment.NewLine); sb.AppendFormat(" <xs:any processContents=\"lax\" minOccurs=\"0\" maxOccurs=\"unbounded\" />{0}", Environment.NewLine); sb.AppendFormat(" </xs:sequence>{0}", Environment.NewLine); // instantiate view to get detailed information about each view field var view = ViewData.CreateView(viewType.ViewTypeName, temporaryRootView, temporaryRootView); view.InitializeViews(); var viewFields = new List <string>(viewType.ViewFields); viewFields.AddRange(viewType.DependencyFields); viewFields.AddRange(viewType.MapViewFields.Select(x => x.From)); viewFields.AddRange(viewType.ViewActionFields); viewFields = viewFields.Distinct().ToList(); // create attributes foreach (var viewField in viewFields) { bool isEnum = false; var viewFieldData = view.GetViewFieldData(viewField); if (viewFieldData.ViewFieldType != null && viewFieldData.ViewFieldType.IsEnum) { isEnum = true; enums.Add(viewFieldData.ViewFieldType); } sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", viewField, isEnum ? "Enum" + viewFieldData.ViewFieldTypeName : "xs:string", Environment.NewLine); } sb.AppendFormat(" <xs:anyAttribute processContents=\"skip\" />{0}", Environment.NewLine); sb.AppendFormat(" </xs:complexType>{0}", Environment.NewLine); } Utils.SuppressLogging = false; // destroy temporary root view GameObject.DestroyImmediate(temporaryRootView.gameObject); // add enums foreach (var enumType in enums) { sb.AppendLine(); sb.AppendFormat(" <xs:simpleType name=\"{0}\">{1}", "Enum" + enumType.Name, Environment.NewLine); sb.AppendFormat(" <xs:restriction base=\"xs:string\">{0}", Environment.NewLine); foreach (var enumTypeName in Enum.GetNames(enumType)) { sb.AppendFormat(" <xs:enumeration value=\"{0}\" />{1}", enumTypeName, Environment.NewLine); } sb.AppendFormat(" </xs:restriction>{0}", Environment.NewLine); sb.AppendFormat(" </xs:simpleType>{0}", Environment.NewLine); } // add theme element sb.AppendLine(); sb.AppendFormat(" <xs:element name=\"{0}\" type=\"{0}\" />{1}", "Theme", Environment.NewLine); sb.AppendFormat(" <xs:complexType name=\"{0}\">{1}", "Theme", Environment.NewLine); sb.AppendFormat(" <xs:sequence>{0}", Environment.NewLine); sb.AppendFormat(" <xs:any processContents=\"lax\" minOccurs=\"0\" maxOccurs=\"unbounded\" />{0}", Environment.NewLine); sb.AppendFormat(" </xs:sequence>{0}", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "BaseDirectory", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Name", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "UnitSize", "xs:string", Environment.NewLine); sb.AppendFormat(" </xs:complexType>{0}", Environment.NewLine); // add resource dictionary element sb.AppendLine(); sb.AppendFormat(" <xs:element name=\"{0}\" type=\"{0}\" />{1}", "ResourceDictionary", Environment.NewLine); sb.AppendFormat(" <xs:complexType name=\"{0}\">{1}", "ResourceDictionary", Environment.NewLine); sb.AppendFormat(" <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">{0}", Environment.NewLine); sb.AppendFormat(" <xs:element name=\"Resource\" type=\"Resource\" minOccurs=\"0\" maxOccurs=\"unbounded\" />{0}", Environment.NewLine); sb.AppendFormat(" <xs:element name=\"ResourceGroup\" type=\"ResourceGroup\" minOccurs=\"0\" maxOccurs=\"unbounded\" />{0}", Environment.NewLine); sb.AppendFormat(" </xs:sequence>{0}", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Name", "xs:string", Environment.NewLine); sb.AppendFormat(" </xs:complexType>{0}", Environment.NewLine); // add resource element sb.AppendLine(); sb.AppendFormat(" <xs:element name=\"{0}\" type=\"{0}\" />{1}", "Resource", Environment.NewLine); sb.AppendFormat(" <xs:complexType name=\"{0}\">{1}", "Resource", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Key", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Value", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Language", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Platform", "xs:string", Environment.NewLine); sb.AppendFormat(" </xs:complexType>{0}", Environment.NewLine); // add resource group element sb.AppendLine(); sb.AppendFormat(" <xs:element name=\"{0}\" type=\"{0}\" />{1}", "ResourceGroup", Environment.NewLine); sb.AppendFormat(" <xs:complexType name=\"{0}\">{1}", "ResourceGroup", Environment.NewLine); sb.AppendFormat(" <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">{0}", Environment.NewLine); sb.AppendFormat(" <xs:element name=\"Resource\" type=\"Resource\" minOccurs=\"0\" maxOccurs=\"unbounded\" />{0}", Environment.NewLine); sb.AppendFormat(" <xs:element name=\"ResourceGroup\" type=\"ResourceGroup\" minOccurs=\"0\" maxOccurs=\"unbounded\" />{0}", Environment.NewLine); sb.AppendFormat(" </xs:sequence>{0}", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Key", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Value", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Language", "xs:string", Environment.NewLine); sb.AppendFormat(" <xs:attribute name=\"{0}\" type=\"{1}\" />{2}", "Platform", "xs:string", Environment.NewLine); sb.AppendFormat(" </xs:complexType>{0}", Environment.NewLine); sb.AppendLine("</xs:schema>"); // save file var path = Configuration.Instance.SchemaFile; string localPath = path.StartsWith("Assets/") ? path.Substring(7) : path; File.WriteAllText(String.Format("{0}/{1}", Application.dataPath, localPath), sb.ToString()); // print result Debug.Log(String.Format("[MarkLight] Schema generated at \"{0}\"", Configuration.Instance.SchemaFile)); }
/// <summary> /// Generates documentation from an XML file. /// </summary> public void GenerateDocumentation() { // Add the following to the Source.CSharp.csproj file in first PropertyGroup // <DocumentationFile>Assets\DevTools\Docs\Documentation.XML</DocumentationFile> // parse Assets\DevTools\Docs\Documentation.XML var documentationXml = File.ReadAllText("Assets/DevTools/Docs/Documentation.XML"); var viewTemplate = File.ReadAllText("Assets/DevTools/Docs/ViewDocTemplate.html"); XElement xmlElement = null; try { xmlElement = XElement.Parse(documentationXml); } catch (Exception e) { Debug.LogErrorFormat("Error parsing documentation XML. Exception thrown: {0}", Utils.GetError(e)); return; } var docData = new List <DocData>(); Utils.SuppressLogging = true; // parse XML comments and create document data objects foreach (var element in xmlElement.Descendants("member").Where(x => x.Attribute("name").Value.StartsWith("T:"))) { var data = new DocData(); // ignore examples, editor, textmeshpro and dev-tools data.FullTypeName = element.Attribute("name").Value.Substring(2); if (data.FullTypeName.StartsWith("MarkLight.Examples") || data.FullTypeName.StartsWith("MarkLight.DevTools") || data.FullTypeName.StartsWith("MarkLight.Editor") || data.FullTypeName.StartsWith("MarkLight.Views.UI.DemoMessage") || data.FullTypeName.StartsWith("TMPro")) { continue; } data.TypeName = data.FullTypeName.Substring(data.FullTypeName.LastIndexOf(".") + 1); // rename `1 for generic types data.FileName = String.Format("{0}.html", data.FullTypeName.Replace("`1", "T")); data.HtmlTypeName = data.TypeName.Replace("`1", "<T>"); data.IsView = ViewPresenter.Instance.ViewTypeDataList.Any(x => x.ViewTypeName == data.TypeName); data.IsType = true; // add summary data.Summary = element.Element("summary").Value.Trim(); // add description var description = element.Element("d"); if (description != null) { data.Description = description.Value.Trim(); } // find all view fields associated with this type foreach (var fieldElement in xmlElement.Descendants("member").Where(x => x.Attribute("name").Value.StartsWith(String.Format("F:{0}.", data.FullTypeName)) || x.Attribute("name").Value.StartsWith(String.Format("P:{0}.", data.FullTypeName)))) { string fieldName = string.Empty; try { // get field summaries and descriptions fieldName = fieldElement.Attribute("name").Value.Substring(2 + data.FullTypeName.Length + 1); if (fieldName.Count(x => x == '.') > 0) { continue; } data.FieldSummaries.Add(fieldName, fieldElement.Element("summary").Value.Trim()); var fieldDescription = fieldElement.Element("d"); if (fieldDescription != null) { data.FieldDescriptions.Add(fieldName, fieldDescription.Value.Trim()); } var fieldActionData = fieldElement.Element("actionData"); if (fieldActionData != null) { data.FieldActionData.Add(fieldName, fieldActionData.Value.Trim()); } // get mapped view field summaries and descriptions foreach (var mappedSummary in fieldElement.Elements("maps")) { var mapField = mappedSummary.Attribute("field").Value; data.FieldSummaries.Add(mapField, mappedSummary.Value.Trim()); data.MappedFields.Add(mapField); } foreach (var mappedDescription in fieldElement.Elements("mapd")) { var mapField = mappedDescription.Attribute("field").Value; data.FieldDescriptions.Add(mapField, mappedDescription.Value.Trim()); } } catch (Exception e) { Utils.SuppressLogging = false; Utils.LogError("Error generating documentation for {0}, when processing field {1}. {2}{3}", data.HtmlTypeName, fieldName, e.Message, e.StackTrace); Utils.SuppressLogging = true; } } docData.Add(data); //Debug.LogFormat("{0}: {1}", data.FileName, data.HtmlTypeName); } System.IO.Directory.CreateDirectory("Assets/DevTools/Docs/API/"); // sort by name docData = docData.OrderBy(x => x.TypeName).ToList(); // generate TOC for views and types var viewDocs = docData.Where(x => x.IsView); var viewsTocSb = new StringBuilder(); foreach (var viewDoc in viewDocs) { viewsTocSb.AppendFormat("<h5><a href=\"{0}\">{1}</a></h5>", viewDoc.FileName, viewDoc.HtmlTypeName); } var viewsToc = viewsTocSb.ToString(); var typesDocs = docData.Where(x => !x.IsView); foreach (var viewDoc in viewDocs) { viewsTocSb.AppendFormat("<h5><a href=\"{0}\">{1}</a></h5>", viewDoc.FileName, viewDoc.HtmlTypeName); } var typesToc = viewsTocSb.ToString(); var layoutRoot = ViewPresenter.Instance.RootView.GetComponent <View>(); var rootView = ViewData.CreateView <View>(layoutRoot, layoutRoot); // generate view content documentation foreach (var data in viewDocs) { var viewTypeData = ViewPresenter.Instance.ViewTypeDataList.First(x => x.ViewTypeName == data.TypeName); var type = ViewData.GetViewType(data.TypeName); if (type == null) { continue; } // section: title var sb = new StringBuilder(); sb.AppendFormat("<h1>{0}</h1>", data.HtmlTypeName); // section: inherits from if (type.BaseType != null && type.BaseType.FullName.StartsWith("MarkLight")) { var inheritsFromData = docData.FirstOrDefault(x => x.FullTypeName == type.BaseType.FullName); if (inheritsFromData != null) { sb.AppendFormat("<h3 class=\"inherit-info\">Inherits from <a href=\"{0}\">{1}</a></h3>", inheritsFromData.FileName, inheritsFromData.HtmlTypeName); } } // section: used by var usedByList = ViewPresenter.Instance.ViewTypeDataList.Where(x => x.DependencyNames.Contains(data.TypeName)) .Select(x => viewDocs.FirstOrDefault(y => y.TypeName == x.ViewTypeName)).Where(x => x != null).ToList(); if (usedByList.Count > 0) { sb.Append("<small class=\"inherit-info\">Used by:"); foreach (var usedBy in usedByList) { sb.AppendFormat(" <a href=\"{0}\">{1}</a>", usedBy.FileName, usedBy.HtmlTypeName); } sb.Append("</small><br>"); } sb.Append("<br>"); // section: description if (!String.IsNullOrEmpty(data.Summary)) { sb.AppendFormat("<h2>Description</h2>{0}<br><br>", !String.IsNullOrEmpty(data.Description) ? data.Description : data.Summary); } // section: fields var viewFields = new List <string>(viewTypeData.ViewFields); viewFields.AddRange(viewTypeData.DependencyFields); viewFields.AddRange(viewTypeData.MapViewFields.Select(x => x.From)); viewFields = viewFields.Distinct().ToList(); if (viewFields.Count > 0) { sb.Append("<h2>View Fields</h2>"); sb.Append("<table class=\"table table-condensed table-hover viewTableViewFields\">"); sb.Append("<thead><tr><th>Name</th><th class=\"col-lg-2\">Type</th><th>Description</th><th class=\"tableExpandColumn\"></th></tr></thead>"); sb.Append("<tbody>"); // get information about view field var view = ViewData.CreateView(data.TypeName, rootView, rootView); view.InitializeViews(); int viewFieldIndex = 0; foreach (var viewField in viewFields.OrderBy(x => x)) { // get view field type information var viewFieldData = view.GetViewFieldData(viewField); var viewFieldTypeSummary = viewFieldData.ViewFieldTypeName; var viewFieldTypeDoc = docData.FirstOrDefault(x => x.TypeName == viewFieldTypeSummary); if (viewFieldTypeDoc != null) { viewFieldTypeSummary = String.Format("<a href=\"{0}\">{1}</a>", viewFieldTypeDoc.FileName, viewFieldTypeDoc.HtmlTypeName); } else { // check if the type is a Unity type if (viewFieldData.ViewFieldType.FullName.StartsWith("UnityEngine")) { // reference the unity docs viewFieldTypeSummary = String.Format("<a href=\"http://docs.unity3d.com/ScriptReference/{0}.html\">{1} <i class=\"fa fa-external-link fa-tiny\"></i></a>", viewFieldTypeSummary, viewFieldTypeSummary); } else { // replace Boolean, String, Single, Object, etc. if (viewFieldTypeSummary == "Boolean") { viewFieldTypeSummary = "bool"; } else if (viewFieldTypeSummary == "Int32") { viewFieldTypeSummary = "int"; } else if (viewFieldTypeSummary == "Single") { viewFieldTypeSummary = "float"; } else if (viewFieldTypeSummary == "String") { viewFieldTypeSummary = "string"; } else if (viewFieldTypeSummary == "Object") { viewFieldTypeSummary = "object"; } } } // add summary row var baseViewDoc = data; if (String.IsNullOrEmpty(baseViewDoc.GetFieldSummary(viewField))) { // check if field summary exist in any of the base types var baseType = view.GetType().BaseType; while (baseType != null && baseType != typeof(object)) { baseViewDoc = docData.FirstOrDefault(x => x.TypeName == baseType.Name); if (baseViewDoc != null && !String.IsNullOrEmpty(baseViewDoc.GetFieldSummary(viewField))) { break; } baseType = baseType.BaseType; } } if (baseViewDoc == null) { baseViewDoc = data; } // find mapped field path string mappedPath = String.Empty; bool isMappedViewField = viewTypeData.MapViewFields.Any(x => x.From == viewField); if (isMappedViewField) { ViewFieldData prevVp = null; for (int i = 0; ; ++i) { var vp = view.GetViewFieldData(viewField, i); if (vp == prevVp) { break; } prevVp = vp; // strip away the last view field which points to the new mapped field int lastDot = mappedPath.LastIndexOf("."); mappedPath = lastDot > 0 ? mappedPath.Substring(0, lastDot + 1) : String.Empty; mappedPath += vp.ViewFieldPath; } } sb.AppendFormat("<tr data-toggle=\"collapse\" data-target=\"#viewFieldDetails{0}\" class=\"accordion-toggle clickable\"><td class=\"{1}\">{2}{3}</td><td class=\"viewFieldType\">{4}</td><td class=\"viewTableSummary\">{5}</td><td><button class=\"btn btn-default btn-xs\"><span class=\"glyphicon glyphicon-plus\"></span></button></td></tr>", viewFieldIndex, isMappedViewField ? "mappedViewFieldName" : "viewFieldName", viewField, isMappedViewField ? String.Format(" <i class=\"fa fa-mail-forward\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"{0}\"></i>", mappedPath) : String.Empty, viewFieldTypeSummary, baseViewDoc.GetFieldSummary(viewField)); // add expandable details row var fieldDescription = baseViewDoc.GetFieldDescription(viewField); sb.AppendFormat("<tr><td colspan=\"4\" class=\"hiddenRow\"><div class=\"accordion-body collapse viewFieldDetails\" id=\"viewFieldDetails{0}\"><div class=\"viewFieldDetailsContent\">{1}", viewFieldIndex, baseViewDoc.GetFieldDescription(viewField)); // ... add additional information if it's an enum type if (viewFieldData.ViewFieldType != null && viewFieldData.ViewFieldType.IsEnum) { if (!String.IsNullOrEmpty(fieldDescription)) { sb.Append("<br><br>"); } sb.Append("<b>Enum Values</b><table class=\"table table-condensed\"><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody>"); var enumData = docData.FirstOrDefault(x => x.FullTypeName == viewFieldData.ViewFieldType.FullName); if (enumData != null) { foreach (var enumFieldName in enumData.FieldSummaries.Keys) { sb.AppendFormat("<tr><td>{0}</td><td>{1}</td></tr>", enumFieldName, enumData.FieldSummaries[enumFieldName]); } } else { var memberInfos = viewFieldData.ViewFieldType.GetMembers(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); for (int i = 0; i < memberInfos.Length; ++i) { sb.AppendFormat("<tr><td>{0}</td><td></td></tr>", memberInfos[i].Name); } } sb.Append("</tbody></table>"); } sb.Append("</div></div></td></tr>"); ++viewFieldIndex; } sb.Append("</tbody>"); sb.Append("</table><br>"); // section: view actions var viewActionFieldData = viewTypeData.ViewActionFields; if (viewActionFieldData.Count > 0) { sb.Append("<h2>View Actions</h2>"); sb.Append("<table class=\"table table-condensed table-hover viewTableViewActions\">"); sb.Append("<thead><tr><th>Name</th><th>Action Data</th><th>Description</th><th class=\"tableExpandColumn\"></th></tr></thead>"); sb.Append("<tbody>"); int viewActionIndex = 0; foreach (var viewFieldData in viewActionFieldData) { var viewActionData = data.GetFieldActionData(viewFieldData); if (!String.IsNullOrEmpty(viewActionData)) { // find the type var actionDataDoc = docData.FirstOrDefault(x => x.IsType && x.TypeName == viewActionData); if (actionDataDoc != null) { viewActionData = String.Format("<a href=\"{0}\">{1}</a>", actionDataDoc.FileName, actionDataDoc.HtmlTypeName); } } else { viewActionData = "none"; } // get view action field summary var baseViewDoc = data; if (String.IsNullOrEmpty(baseViewDoc.GetFieldSummary(viewFieldData))) { // check if field summary exist in any of the base types var baseType = view.GetType().BaseType; while (baseType != null && baseType != typeof(object)) { baseViewDoc = docData.FirstOrDefault(x => x.TypeName == baseType.Name); if (baseViewDoc != null && !String.IsNullOrEmpty(baseViewDoc.GetFieldSummary(viewFieldData))) { break; } baseType = baseType.BaseType; } } if (baseViewDoc == null) { baseViewDoc = data; } // get action data sb.AppendFormat("<tr data-toggle=\"collapse\" data-target=\"#viewActionDetails{0}\" class=\"accordion-toggle clickable\"><td class=\"viewFieldName\">{1}{2}</td><td class=\"viewFieldType\">{3}</td><td class=\"viewTableSummary\">{4}</td><td><button class=\"btn btn-default btn-xs\"><span class=\"glyphicon glyphicon-plus\"></span></button></td></tr>", viewActionIndex, viewFieldData, String.Empty, viewActionData, baseViewDoc.GetFieldSummary(viewFieldData)); // add expandable details row sb.AppendFormat("<tr><td colspan=\"4\" class=\"hiddenRow\"><div class=\"accordion-body collapse viewFieldDetails\" id=\"viewActionDetails{0}\"><div class=\"viewFieldDetailsContent\">{1}</div></div></td></tr>", viewActionIndex, baseViewDoc.GetFieldDescription(viewFieldData)); ++viewActionIndex; } sb.Append("</tbody>"); sb.Append("</table><br>"); } } data.DocContent = sb.ToString(); } GameObject.DestroyImmediate(rootView.gameObject); // generate view content documentation foreach (var data in typesDocs) { // section: title var sb = new StringBuilder(); sb.AppendFormat("<h1>{0}</h1>", data.HtmlTypeName); sb.Append("<br>"); // section: description if (!String.IsNullOrEmpty(data.Summary)) { sb.AppendFormat("<h2>Description</h2>{0}<br><br>", !String.IsNullOrEmpty(data.Description) ? data.Description : data.Summary); } data.DocContent = sb.ToString(); } // generate HTML files foreach (var doc in docData) { var viewToc = viewsToc.Replace(String.Format(">{0}<", doc.HtmlTypeName), String.Format(" class=\"sectionSelected\">{0}<", doc.HtmlTypeName)); var fileContent = viewTemplate.Replace("__TITLE__", doc.HtmlTypeName) .Replace("__TOC__", doc.IsView ? viewToc : typesToc).Replace("__CONTENT__", doc.DocContent); // write text to file File.WriteAllText(String.Format("C:/Projects/Websites/marklightforunity.com/www/docs/api/{0}", doc.FileName), fileContent); } // generate sitemap.xml file var sitemapSb = new StringBuilder(); sitemapSb.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sitemapSb.AppendLine("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\""); sitemapSb.AppendLine(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); sitemapSb.AppendLine(" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\">"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/index.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/introduction.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/animations.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/data-binding.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/gettingstarted.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/how-to-get-intellisense.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/how-to-move-marklight.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/resource-dictionaries.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/state-management.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/themes-and-styles.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/view-model.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/tutorials/working-with-list-data.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/news/marklight-2.1.0-released.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/news/marklight-2.2.0-released.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/news/marklight-2.3.0-released.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/news/marklight-2.4.1-released.html</loc>"); sitemapSb.AppendLine(" </url>"); sitemapSb.AppendLine(" <url>"); sitemapSb.AppendLine(" <loc>http://www.marklightforunity.com/docs/news/marklight-2.5.0-released.html</loc>"); sitemapSb.AppendLine(" </url>"); foreach (var doc in docData) { sitemapSb.AppendLine(" <url>"); sitemapSb.AppendFormat(" <loc>http://www.marklightforunity.com/docs/api/{0}</loc>{1}", doc.FileName, Environment.NewLine); sitemapSb.AppendLine(" </url>"); } sitemapSb.AppendLine("</urlset>"); File.WriteAllText("C:/Projects/Websites/marklightforunity.com/www/sitemap.xml", sitemapSb.ToString()); Utils.SuppressLogging = false; Utils.Log("Documentation generated"); }