' DocGeneratorCS class ' ' Generates html and markdown documentation for C# code from compiler-generated xml files based on three-slash ( /// ) code comments. ' ' Four base tags are supported: summary, parameters, returns, and remarks. Within these tags, html tags are allowed, although Markdown typically does not render all html tags. ' ' Note: When changes are made to source-code comments, the code must be compiled again in order for new .xml files to be generated, before running the doc-generator script. ' ' Note: Html tags may result in malformed markdown table rows when there is whitespace between adjacent tags. ' Class DocGeneratorCS Private xml 'MSXML2.DomDocument.6.0 object Private html 'text stream object for writing Private md 'text stream object for writing Private xmlFile 'filespec Private outFile_ 'partial filespec Private htmlFile 'filespec of html output file Private mdFile 'filespec of markdown output file Private fso 'Scripting.FileSystemObject object Private sh 'WScript.Shell object Private f 'VBScripting.StringFormatter object Private ForWriting, CreateNew 'faux constants for OpenTextFile Sub Class_Initialize Set fso = CreateObject( "Scripting.FileSystemObject" ) Set sh = CreateObject( "WScript.Shell" ) Set f = CreateObject( "VBScripting.StringFormatter" ) Set xml = CreateObject( "MSXML2.DomDocument.6.0" ) With CreateObject( "VBScripting.Includer" ) ExecuteGlobal .Read( "EscapeMd" ) End With xml.Async = False ForWriting = 2 CreateNew = True End Sub Sub Class_Terminate Set xml = Nothing On Error Resume Next html.Close md.Close On Error Goto 0 Set html = Nothing Set md = Nothing Set fso = Nothing Set sh = Nothing Set f = Nothing End Sub 'Property XmlFolder 'Parameter: folder 'Returns: folder 'Remarks: Required. Sets (or gets) the folder containing the .xml files autogenerated by the C# compiler. Relative paths and environment variables are supported. Property Get XmlFolder XmlFolder = sh.ExpandEnvironmentStrings(xmlFolder_) End Property Property Let XmlFolder(newFolder) xmlFolder_ = newFolder ValidateXmlFolder End Property Private xmlFolder_ 'Property OutputFile 'Parameters: filespec 'Returns: filespec 'Remarks: Required. Sets (or gets) the path and base name of the output files. Do not include the .html or .md extension name: they will be added automatically. Older versions, if any, will be overwritten. Relative paths and environment variables are supported. Property Get OutputFile OutputFile = Expand(outFile_) End Property Property Let OutputFile(newValue) outFile_ = newValue htmlFile = Expand(outFile_) & ".html" mdFile = Expand(outFile_) & ".md" End Property Function Expand(path) Expand = sh.ExpandEnvironmentStrings(path) End Function 'Method Generate 'Remarks: Generates html and markdown code documentation. Requires .xml files to have been generated by the C# compiler. Sub Generate ValidateXmlFolder WriteHtmlHeader WriteMarkdownHeader Dim file For Each file In fso.GetFolder(xmlFolder_).Files GenerateTable file.Path Next WriteHtmlFooter End Sub 'Method ViewHtml 'Remarks: Opens the html document with the default viewer. Sub ViewHtml sh.Run """" & htmlFile & """" End Sub 'Method ViewMarkdown 'Remarks: Opens the markdown document with the default viewer. Sub ViewMarkdown sh.Run """" & mdFile & """" End Sub Sub GenerateTable(xmlFile) Dim member 'xml node object for a C# class member If Not "xml" = LCase(fso.GetExtensionName(xmlFile)) Then Exit Sub End If xml.Load xmlFile If xml.ParseError.ErrorCode Then Err.Raise xml.ParseError.ErrorCode,, xml.ParseError.Reason & vbLf & "File: " & xmlFile End If GenerateHtmlTableHeader xmlFile GenerateMarkdownTableHeader xmlFile For Each member In xml.getElementsByTagName( "member" ) GenerateRow member Next html.WriteLine "" End Sub Sub GenerateHtmlTableHeader(xmlFile) html.WriteLine "" html.WriteLine "

" & fso.GetBaseName(xmlFile) & "

" html.WriteLine "" html.WriteLine " " html.WriteLine " " html.WriteLine " " html.WriteLine " " html.WriteLine " " html.WriteLine " " html.WriteLine " " html.WriteLine " " html.WriteLine " " End Sub Sub GenerateMarkdownTableHeader(xmlFile) md.WriteLine "" md.WriteLine "## " & fso.GetBaseName(xmlFile) md.WriteLine "" md.WriteLine "| Member name | Remarks | Returns | Parameters | Kind | Member of | Namespace |" md.WriteLine "| :---------- | :------ | :------ | :--------- | :--- | :-------- | :-------- |" End Sub Sub GenerateRow(member) Dim info : Set info = GetMemberInfo(member) If Len(Trim(info.Summary & info.Remarks)) < 3 And 0 = Len(Trim(info.Returns)) Then Exit Sub End If GenerateHtmlRow info GenerateMarkdownRow info End Sub Sub GenerateHtmlRow(info) html.WriteLine " " html.WriteLine f(Array(" ", info.Name)) html.WriteLine f(Array(" ", info.Summary & " " & info.Remarks)) html.WriteLine f(Array(" ", info.Returns)) html.WriteLine f(Array(" ", info.Parameters)) html.WriteLine f(Array(" ", info.Kind)) If "Type" = info.Kind Then html.WriteLine " " Else html.WriteLine f(Array(" ", info.MemberOf)) End If html.WriteLine f(Array(" ", info.NamespaceName)) html.WriteLine " " End Sub Sub GenerateMarkdownRow(info) md.Write f(Array("| %s ", info.Name)) md.Write f(Array("| %s ", EscapeMd2(info.Summary & " " & info.Remarks))) md.Write f(Array("| %s ", info.Returns)) md.Write f(Array("| %s ", info.Parameters)) md.Write f(Array("| %s ", info.Kind)) If "Type" = info.Kind Then md.Write "| " Else md.Write f(Array("| %s ", info.MemberOf)) End If md.Write f(Array("| %s ", info.NamespaceName)) md.WriteLine "|" End Sub 'Return a MemberInfo object suitable for use in creating a row in the html or markdown table. The argument "member" is an xml node/object. Function GetMemberInfo(member) Dim info 'MemberInfo object Dim child 'xml dom object Dim attribute 'xml attribute object Dim rawName 'string Set info = New MemberInfo For Each attribute In member.attributes If "name" = attribute.name Then rawName = attribute.text End If Next info.Kind = GetKind(rawName) info.NamespaceName = GetNamespaceName(rawName) info.MemberOf = GetTypeName(rawName) If "Type" = info.Kind Then info.Name = info.MemberOf info.MemberOf = "" Else info.Name = GetName(rawName) End If If "#ctor" = info.Name Then info.Name = "(Constructor)" End If Set GetMemberInfo = info If Not member.hasChildNodes Then Exit Function End If For Each child In member.childNodes Select case child.nodeName Case "summary" info.Summary = innerHTML(child) Case "remarks" info.Remarks = innerHTML(child) Case "parameters" info.Parameters = innerHTML(child) Case "returns" info.Returns = innerHTML(child) End Select Next Set GetMemberInfo = info End Function Function innerHTML(child) Dim str 'string of xml to be parsed Dim tag 'xml tag name str = child.xml tag = child.nodeName str = Replace(str, f(Array("<%s>", tag)), "") innerHTML = Trim(Replace(str, f(Array("", tag)), "")) End Function Function GetKind(rawName) 'ByRef by default Select Case Left(rawName, 1) Case "T" : GetKind = "Type" Case "P" : GetKind = "Property" Case "M" : GetKind = "Method" Case "F" : GetKind = "Field" End Select rawName = Right(rawName, Len(rawName) - 2) End Function Function GetNamespaceName(rawName) 'ByRef by default GetNamespaceName = Left(rawName, InStr(rawName, ".") - 1) rawName = Right(rawName, Len(rawName) - Len(GetNamespaceName) - 1) End Function Function GetTypeName(rawName) If InStr(rawName, ".") Then GetTypeName = Left(rawName, InStr(rawName, ".") - 1) rawName = Right(rawName, Len(rawName) - Len(GetTypeName) - 1) Else GetTypeName = rawName rawName = "" End If End Function Function GetName(rawName) If InStr(rawName, "(") Then GetName = Left(rawName, InStr(rawName, "(") - 1) Else GetName = rawName End If End Function Sub WriteHtmlHeader On Error Resume Next Set html = fso.OpenTextFile(htmlFile, ForWriting, CreateNew) If Err Then MsgBox "Use the OutputFile property to set the output file.", vbInformation, "DocGeneratorCS class" Class_Terminate WScript.Quit 'for .vbs or .wsf script Self.Close 'for .hta End If On Error Goto 0 html.WriteLine "" html.WriteLine "" html.WriteLine "" html.WriteLine "" html.WriteLine "" html.WriteLine "

C# Classes Documentation

" End Sub Sub WriteMarkdownHeader Dim file 'file object Dim baseName 'string: partial filename On Error Resume Next Set md = fso.OpenTextFile(mdFile, ForWriting, CreateNew) If Err Then MsgBox "Use the OutputFile property to set the output file.", vbInformation, "DocGeneratorCS class" Class_Terminate WScript.Quit 'for .vbs or .wsf script Self.Close 'for .hta End If On Error Goto 0 md.WriteLine "# C# Classes Documentation" md.WriteLine "" md.WriteLine "### Contents" md.WriteLine "" For Each file In fso.GetFolder(xmlFolder_).Files If "xml" = LCase(fso.GetExtensionName(file.Name)) Then baseName = fso.GetBaseName(file.Name) md.WriteLine f(Array("[%s](#%s) ", baseName, LCase(baseName))) End If Next md.WriteLine "" End Sub Sub WriteHtmlFooter html.WriteLine "" html.WriteLine "" html.WriteLine "" html.WriteLine "" End Sub Sub ValidateXmlFolder If Not fso.FolderExists(xmlFolder_) Then Err.Raise 505, "DocGeneratorCS.ValidateXmlFolder", "Set the XmlFolder property to the location of the .xml files." End If End Sub End Class Class MemberInfo Public Kind 'Type, Method, Property, Field Public NamespaceName Public MemberOf 'type name or, for types, namespace name Public Name Public Summary Public Parameters Public Returns Public Remarks End Class
Member name Remarks Returns Parameters Kind Member of Namespace
%s %s %s %s %s %s %s