Mini Kabibi Habibi
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports DevExpress.CodeParser
Imports DevExpress.CodeParser.CSharp
Imports DevExpress.CodeParser.Html
Imports DevExpress.CodeParser.VB
Imports DevExpress.CodeParser.JavaScript
Imports DevExpress.CodeParser.Xml
Imports DevExpress.CodeParser.Css
Imports System.Text
Namespace DevExpress.Web.Demos
Public NotInheritable Class CodeFormatter
Private Shared _cssClasses As New Dictionary(Of TokenCategory, TokenCategoryClassProvider)()
Private Sub New()
End Sub
Shared Sub New()
CssClasses.Add(TokenCategory.Text, New TokenCategoryClassProvider("cr-text", New KeyValuePair(Of TokenLanguage, String)(TokenLanguage.Html, "cr-text-html")))
CssClasses.Add(TokenCategory.Keyword, New TokenCategoryClassProvider("cr-keyword", New KeyValuePair(Of TokenLanguage, String)(TokenLanguage.Html, "cr-keyword-html"), New KeyValuePair(Of TokenLanguage, String)(TokenLanguage.Css, "cr-keyword-css")))
CssClasses.Add(TokenCategory.Operator, New TokenCategoryClassProvider("cr-operator"))
CssClasses.Add(TokenCategory.PreprocessorKeyword, New TokenCategoryClassProvider("cr-preproc", New KeyValuePair(Of TokenLanguage, String)(TokenLanguage.Html, "cr-preproc-html")))
CssClasses.Add(TokenCategory.String, New TokenCategoryClassProvider("cr-string", New KeyValuePair(Of TokenLanguage, String)(TokenLanguage.Html, "cr-string-html"), New KeyValuePair(Of TokenLanguage, String)(TokenLanguage.Css, "cr-string-css")))
CssClasses.Add(TokenCategory.Number, New TokenCategoryClassProvider("cr-number"))
CssClasses.Add(TokenCategory.Identifier, New TokenCategoryClassProvider("cr-identifier"))
CssClasses.Add(TokenCategory.HtmlServerSideScript, New TokenCategoryClassProvider("cr-htmlserverscript"))
CssClasses.Add(TokenCategory.HtmlString, New TokenCategoryClassProvider("cr-htmlstring"))
CssClasses.Add(TokenCategory.Unknown, New TokenCategoryClassProvider("cr-unknown"))
CssClasses.Add(TokenCategory.Comment, New TokenCategoryClassProvider("cr-comment"))
CssClasses.Add(TokenCategory.XmlComment, New TokenCategoryClassProvider("cr-xmlcomment"))
CssClasses.Add(TokenCategory.CssComment, New TokenCategoryClassProvider("cr-csscomment"))
CssClasses.Add(TokenCategory.CssKeyword, New TokenCategoryClassProvider("cr-csskeyword"))
CssClasses.Add(TokenCategory.CssPropertyName, New TokenCategoryClassProvider("cr-csspropertyname"))
CssClasses.Add(TokenCategory.CssPropertyValue, New TokenCategoryClassProvider("cr-csspropertyvalue"))
CssClasses.Add(TokenCategory.CssSelector, New TokenCategoryClassProvider("cr-cssselector"))
CssClasses.Add(TokenCategory.CssStringValue, New TokenCategoryClassProvider("cr-cssstringvalue"))
CssClasses.Add(TokenCategory.HtmlElementName, New TokenCategoryClassProvider("cr-htmlelementname"))
CssClasses.Add(TokenCategory.HtmlEntity, New TokenCategoryClassProvider("cr-htmlentity"))
CssClasses.Add(TokenCategory.HtmlOperator, New TokenCategoryClassProvider("cr-htmloperator"))
CssClasses.Add(TokenCategory.HtmlComment, New TokenCategoryClassProvider("cr-htmlcomment"))
CssClasses.Add(TokenCategory.HtmlAttributeName, New TokenCategoryClassProvider("cr-htmlattributename"))
CssClasses.Add(TokenCategory.HtmlAttributeValue, New TokenCategoryClassProvider("cr-htmlattributevalue"))
CssClasses.Add(TokenCategory.HtmlTagDelimiter, New TokenCategoryClassProvider("cr-htmltagdelimiter"))
End Sub
Public Shared ReadOnly Property CssClasses() As Dictionary(Of TokenCategory, TokenCategoryClassProvider)
Get
Return _cssClasses
End Get
End Property
Public Shared Function ParseLanguage(ByVal lang As String) As TokenLanguage
Return CType(System.Enum.Parse(GetType(TokenLanguage), lang, True), TokenLanguage)
End Function
Public Shared Function GetLanguageByFileExtension(ByVal extension As String) As TokenLanguage
Select Case extension.ToLower()
Case ".cs"
Return TokenLanguage.CSharp
Case ".vb"
Return TokenLanguage.Basic
Case ".html", ".htm", ".aspx", ".ascx", ".master", ".cshtml"
Return TokenLanguage.Html
Case ".js"
Return TokenLanguage.JavaScript
Case ".xml"
Return TokenLanguage.Xml
Case ".css"
Return TokenLanguage.Css
Case Else
Return TokenLanguage.Unknown
End Select
End Function
Public Shared Function GetFormattedCode(ByVal fileExtension As String, ByVal code As String) As String
Return GetFormattedCode(GetLanguageByFileExtension(fileExtension), code, False, False)
End Function
Public Shared Function GetFormattedCode(ByVal fileExtension As String, ByVal code As String, ByVal isMvc As Boolean, ByVal isRazor As Boolean) As String
Return GetFormattedCode(GetLanguageByFileExtension(fileExtension), code, isMvc, isRazor)
End Function
Public Shared Function GetFormattedCode(ByVal language As TokenLanguage, ByVal code As String) As String
Return GetFormattedCode(language, code, False, False)
End Function
Public Shared Function GetFormattedCode(ByVal language As TokenLanguage, ByVal code As String, ByVal isMvc As Boolean, ByVal isRazor As Boolean) As String
Dim tokens As TokenCollection = GetTokens(language, code, isMvc, isRazor)
If tokens IsNot Nothing Then
Return GetFormattedCode(code, tokens)
End If
Return String.Empty
End Function
Private Class CodeLine
Public Indent As Integer
Public Html As String = ""
Public ReadOnly Property IsEmpty() As Boolean
Get
Return Html.Trim().Length < 1
End Get
End Property
End Class
Private Shared Function GetFormattedCode(ByVal code As String, ByVal tokens As TokenCollection) As String
Dim currentLine As New CodeLine()
Dim lines As New List(Of CodeLine)()
Dim pos As Integer = 0
For Each token As CategorizedToken In tokens
AppendCode(lines, currentLine, code.Substring(pos, token.StartPosition - pos), Nothing)
AppendCode(lines, currentLine, token.Value, CssClasses(token.Category).GetClassName(token.Language))
pos = token.EndPosition
Next token
AppendCode(lines, currentLine, code.Substring(pos), Nothing)
lines.Add(currentLine)
Return MergeCodeLines(lines)
End Function
Private Shared Sub AppendCode(ByVal lines As List(Of CodeLine), ByRef currentLine As CodeLine, ByVal code As String, ByVal cssClass As String)
Dim hasCss As Boolean = Not String.IsNullOrEmpty(cssClass)
Dim first As Boolean = True
code = code.Replace(Constants.vbCr, "").Replace(Constants.vbTab, " ")
For Each line As String In code.Split(ControlChars.Lf)
Dim text As String = line
If (Not first) Then
lines.Add(currentLine)
currentLine = New CodeLine()
text = text.TrimStart()
currentLine.Indent = line.Length - text.Length
End If
If first OrElse text.Trim().Length > 0 Then
If hasCss Then
currentLine.Html &= String.Format("<span class=""{0}"">", cssClass)
End If
currentLine.Html &= HttpUtility.HtmlEncode(text)
If hasCss Then
currentLine.Html &= "</span>"
End If
End If
first = False
Next line
End Sub
Private Shared Function MergeCodeLines(ByVal lines As List(Of CodeLine)) As String
Dim minIndent As Integer = Integer.MaxValue
For Each line As CodeLine In lines
If line.IsEmpty Then
Continue For
End If
If line.Indent < minIndent Then
minIndent = line.Indent
End If
Next line
Dim result As New StringBuilder()
Dim emptyLineCount As Integer = 0
For Each line As CodeLine In lines
If line.IsEmpty Then
If result.Length > 0 Then
emptyLineCount += 1
End If
Continue For
End If
If emptyLineCount > 0 Then
Dim i As Integer = 0
Do While i < emptyLineCount
result.Append("<br />")
i += 1
Loop
emptyLineCount = 0
End If
Dim indent As Integer = line.Indent - minIndent
For i As Integer = 0 To indent - 1
result.Append(" ")
Next i
result.Append(line.Html)
If result.Length > 0 Then
result.Append("<br />")
End If
Next line
Return result.ToString().Trim()
End Function
Private Shared Function GetTokens(ByVal language As TokenLanguage, ByVal code As String, ByVal isMvc As Boolean, ByVal isRazor As Boolean) As TokenCollection
Select Case language
Case TokenLanguage.CSharp
Return CSharpTokensHelper.GetTokens(code)
Case TokenLanguage.Basic
Return VBTokensHelper.GetTokens(code)
Case TokenLanguage.JavaScript
Return JavaScriptTokensHelper.GetTokens(code)
Case TokenLanguage.Html
If (Not isMvc) Then
Return HtmlTokensHelper.GetTokens(code)
Else
If isRazor Then
Return HtmlTokensHelper.GetTokens(code,LanguageKind.Razor, DotNetLanguageType.CSharp)
Else
Return HtmlTokensHelper.GetTokens(code,LanguageKind.Html, DotNetLanguageType.CSharp)
End If
End If
Case TokenLanguage.Xml
Return New XmlTokensCategoryHelper().GetTokens(code)
Case TokenLanguage.Css
Return New CssTokensCategoryHelper().GetTokens(code)
Case Else
Return Nothing
End Select
End Function
End Class
Public Class TokenCategoryClassProvider
Private className As String
Private languagesClassNames As New Dictionary(Of TokenLanguage, String)()
Public Sub New(ByVal className As String)
Me.New(className, Nothing)
End Sub
Public Sub New(ByVal className As String, ParamArray ByVal languagesClassNames() As KeyValuePair(Of TokenLanguage, String))
Me.className = className
If languagesClassNames IsNot Nothing Then
For Each languageClassName As KeyValuePair(Of TokenLanguage, String) In languagesClassNames
Me.languagesClassNames(languageClassName.Key) = languageClassName.Value
Next languageClassName
End If
End Sub
Public Function GetClassName(ByVal language As TokenLanguage) As String
If Me.languagesClassNames.ContainsKey(language) Then
Return Me.languagesClassNames(language)
End If
Return Me.className
End Function
End Class
End Namespace