2019年3月9日土曜日

[.NET][Edge対応版]プログラムコードの変換(C#、VB.NET→HTML)

[はじめに]
 ・プログラムソース(C#、VB.NET)を
  ブログ公開用のHTMLに変換するツールです。
  (コード量が膨大の為、変換処理のみ掲載しています。)
[機能]
  プログラムソースの文字列を、HTMLに変換する。
  変換後のHTMLは、<table>タグで整形した形になります。
[変換後HTML]
 ・インデントのスペースが「 」に変換され、ブラウザ上でも表示される。
 ・予約語、コメント、文字列(ダブルコーテーションで囲んだ部分)に色がつく。
 ・ソースコードをクリップボードにコピーする機能を提供。(「コードのコピー」ボタンを付加)
  IE、Edgeで動作確認済。
[制限事項]
 ・言語は、C#とVB.NETのみです。
  但し、VB6やVBA等はVB.NETと言語仕様が似ている為、
  制限事項を考慮の上、利用することもできます。
 ・C#のコメントは、行の先頭の「//」のみサポート。
  行の途中の「//」や「/*」~「*/」はサポートしません。
 ・VB.NETのコメントは、行の先頭の「'」のみサポート。
  行の途中の「'」はサポートしません。
[使い方]
 (1)ビルド前に、「System.Web」を参照設定に追加する。
   追加しないとコンパイルエラーになります。
 (2)CodeConverterToHtml クラスのGetInstanceメソッドで、
   変換オブジェクトを取得します。
   言語の種類(C#かVB.NET)は、GetInstanceメソッドの第1引数で指定します。 
 (3)CodeConverterToHtml クラスのConvertCodeToHtmlメソッドで、
   ソースをHTMLに変換します。
   ConvertCodeToHtmlメソッドの仕様
   ・第1引数:プログラムソースの文字列
   ・第2引数:整形後HTMLのタイトル。(省略可能)
   ・戻り値:変換後のHTMLの文字列
        変換後の文字列(HTML)は、
        <table>タグで整形した形となります。
        (<html>タグでは囲みません。)
'変換クラスを取得する。
Dim conv As CodeConverterToHtml = _
        CodeConverterToHtml.GetInstance( _
            CodeConverterToHtml.ProgLangType.VBNet _
        )

'プログラムソース
Dim strPgSource As String = "・…(プログラムソース)…"

'変換処理(変換結果はブログ等に貼り付けて、利用できます。)
Dim strConv As String = _
    conv.ConvertCodeToHtml(strPgSource, "[VB.NET]変換機能の使用例")
[VB.NET]変換機能の使用例

[改造ポイント]
 ・拡張性
  言語(C#、VB.NET)の固有ロジックを、
  CodeConverterToHtml の派生クラスに定義しています。
  (VBCodeConverterToHtml、CSharpCodeConverterToHtml)
  予約語一覧、キーワードの前景色、背景色、検索条件(正規表現)、変換仕様は、
  派生クラスの修正で変更できます。
  また、言語を追加する場合も、既存の派生クラスの流用が簡単です。
 ・予約語一覧
  予約語一覧は各派生クラスに定義しています。
  予約語の追加、変更、削除が簡単です。
 ・キーワードの検索条件
  正規表現を各派生クラスに定義しています。
  正規表現を修正することで、キーワードの検索条件を変更できます。
 ・キーワードの変換仕様
  正規表現の検索結果毎に、
  MatchEvaluator()メソッドが呼ばれます。
  MatchEvaluator()メソッドの修正で変換仕様を変更できます。
 ・マルチスレッド対応
  スレッドセーフではありません。
  派生クラスのGetRegEx() とGetReservedWords()に、
  複数スレッドが同時アクセスした場合、
  m_RegEx変数、m_ReservedWords変数の値に
  矛盾が生じる可能性があります。
  ASP.NET等のマルチスレッド環境で安全に使用する為には、
  SyncLockで排他をかける必要があります。

[プログラムソース]
Imports System.Text.RegularExpressions
''' <summary>
''' 変換(ソースコード→HTML)
''' </summary>
''' <remarks></remarks>
Public MustInherit Class CodeConverterToHtml

#Region "定数定義"
    ''' <summary>
    ''' HTMLレイアウト
    ''' </summary>
    ''' <remarks></remarks>
    Private Const TABLE_STRING As String =
        "<table width=""100%"" border=""0"" " &
        " bgcolor=""@@@TITLEBGCOLOR@@@"" " &
        " cellspacing=""0"">" &
        " <tr><td>" &
        "  <button type=""button"" value="""" " &
        "   onClick=""" &
        "   var ta=document.createElement('textarea');" &
        "   ta.value=this.parentNode.parentNode.parentNode.getElementsByTagName('tr')[1].innerText;" &
        "   this.appendChild(ta);ta.select();" &
        "   document.execCommand('Copy');" &
        "   alert('コピーしました。');" &
        "   this.removeChild(ta);"">" &
        "   コードのコピー</button>" &
        " </td></tr>" &
        " <tr><td>" &
        " <table width=""100%"" border=""0"" " &
        "  cellpadding=""10"" " &
        "  bgcolor=""@@@BGCOLOR@@@"" " &
        "  cellspacing=""0"">" &
        "  <tr><td>" &
        "   <font color=""@@@FORECOLOR@@@"" " &
        "    style=""font-size: 9pt"">" &
        "    <code>@@@CODE@@@</code>" &
        "   </font>" &
        "  </td></tr>" &
        " </table>" &
        " </td></tr>" &
        " <tr><td>" &
        " <b><font size=""2"">@@@TITLE@@@</font></b>" &
        " </td></tr>" &
        "</table>"
#End Region

#Region "列挙定義"
    ''' <summary>
    ''' 言語の種類
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum ProgLangType
        ''' <summary>
        ''' VB.NET
        ''' </summary>
        ''' <remarks></remarks>
        VBNet = 0
        ''' <summary>
        ''' C#.NET
        ''' </summary>
        ''' <remarks></remarks>
        CSharp = 1
    End Enum

#End Region

#Region "変数定義"
    ''' <summary>
    ''' インスタンス
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared instanceList() As CodeConverterToHtml = _
        New CodeConverterToHtml() { _
            New VbCodeConverterToHtml(), _
            New CSharpCodeConverterToHtml() _
        }

#End Region

#Region "コンストラクタ"
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub New()

    End Sub

#End Region

#Region "インスタンスを取得"
    ''' <summary>
    ''' インスタンスを取得
    ''' </summary>
    ''' <param name="type">言語の種類</param>
    ''' <returns>インスタンス</returns>
    ''' <remarks></remarks>
    Public Shared Function GetInstance( _
        ByVal type As ProgLangType) As CodeConverterToHtml

        Return instanceList(type)
    End Function
#End Region

#Region "ソースコードをHTMLに変換する。"
    ''' <summary>
    ''' ソースコードをHTMLに変換する。
    ''' </summary>
    ''' <param name="src">ソースコード</param>
    ''' <returns>HTML</returns>
    ''' <remarks></remarks>
    Public Function ConvertCodeToHtml(ByVal src As String) As String
        Return Me.ConvertCodeToHtml(src, Me.GetDefaultTitle())
    End Function

    ''' <summary>
    ''' ソースコードをHTMLに変換する。
    ''' </summary>
    ''' <param name="src">ソースコード</param>
    ''' <param name="title">タイトル</param>
    ''' <returns>HTML</returns>
    ''' <remarks></remarks>
    Public Function ConvertCodeToHtml( _
        ByVal src As String, ByVal title As String) As String

        Dim wkSrcList() As String = Nothing

        'ソースコードを行単位に分割する。
        '(vbCrLf, vbLf, vbCr毎)
        wkSrcList = src.Split( _
            New String() {vbCrLf, vbLf, vbCr}, _
            StringSplitOptions.None)

        '先頭の空白文字数を取得
        Dim cntIndent As Integer = _
            Me.GetHeadSpaceCount(wkSrcList)

        '先頭の空白文字を削除
        Me.RemoveStringList(wkSrcList, cntIndent)

        'HTMLエンコード
        Me.HtmlEncode(wkSrcList)

        Dim regEx As Regex = Me.GetRegEx()
        Dim regMatchEvaluator As _
            New MatchEvaluator(AddressOf Me.MatchEvaluator)

        'キーワードにタグを付加
        For i As Integer = 0 To wkSrcList.Length - 1
            wkSrcList(i) = wkSrcList(i).Replace( _
                    " ", "&nbsp;")
            wkSrcList(i) = regEx.Replace( _
                    wkSrcList(i), regMatchEvaluator)
        Next

        Dim wkStr As String

        wkStr = String.Join(vbCrLf, wkSrcList)
        wkStr = wkStr.Replace(vbCrLf, "<br/>" & vbCrLf)

        Dim wkStrTable As String = Nothing

        wkStrTable = TABLE_STRING.Replace( _
            "@@@TITLE@@@", title)
        wkStrTable = wkStrTable.Replace( _
            "@@@BGCOLOR@@@", Me.GetBackColor())
        wkStrTable = wkStrTable.Replace( _
            "@@@FORECOLOR@@@", Me.GetForeColor())
        wkStrTable = wkStrTable.Replace( _
            "@@@TITLEBGCOLOR@@@", Me.GetTitleBackColor())
        wkStr = wkStrTable.Replace("@@@CODE@@@", wkStr)


        Return wkStr
    End Function

#Region "ヘルパーメソッド"
    ''' <summary>
    ''' HTMLにエンコードする
    ''' </summary>
    ''' <param name="srcLineList">ソース</param>
    ''' <returns>ソース(HTMLエンコード済)</returns>
    ''' <remarks></remarks>
    Private Function HtmlEncode(ByVal srcLineList() As String) As String()

        For i As Integer = 0 To srcLineList.Length - 1
            srcLineList(i) = System.Web.HttpUtility.HtmlEncode(srcLineList(i))
        Next

        Return srcLineList

    End Function

    ''' <summary>
    ''' インデントの桁数を取得。
    ''' </summary>
    ''' <param name="srcLineList">ソース</param>
    ''' <returns>インデントの桁数</returns>
    ''' <remarks></remarks>
    Private Function GetHeadSpaceCount( _
        ByVal srcLineList() As String) As Integer

        Const CHR_BLANK As Char = " "c
        Return Me.GetHeadSpaceCount(srcLineList, CHR_BLANK)
    End Function

    ''' <summary>
    ''' インデントの桁数を取得。
    ''' </summary>
    ''' <param name="srcLineList">ソース</param>
    ''' <param name="indentChar">インデントの文字</param>
    ''' <returns>インデントの桁数</returns>
    ''' <remarks></remarks>
    Private Function GetHeadSpaceCount( _
        ByVal srcLineList() As String, _
        ByVal indentChar As Char) As Integer

        Dim cntIndent As Integer = Int32.MaxValue

        If srcLineList.Length = 0 Then
            Return 0
        End If

        For Each wkSrc As String In srcLineList

            For i As Integer = 0 To wkSrc.Length - 1

                If wkSrc.Trim() = "" Then
                    Exit For
                End If

                If i >= cntIndent Then
                    Exit For
                End If

                If wkSrc(i) = indentChar.ToString() Then

                Else
                    cntIndent = Math.Min(i, cntIndent)
                    Exit For
                End If
            Next
        Next

        If cntIndent = Int32.MaxValue Then
            Return 0
        End If

        Return cntIndent

    End Function

    ''' <summary>
    ''' 各行からインデントを除去する。
    ''' </summary>
    ''' <param name="srcLineList">ソース</param>
    ''' <param name="cnt">インデントの桁数</param>
    ''' <returns>処理結果</returns>
    ''' <remarks></remarks>
    Private Function RemoveStringList( _
        ByVal srcLineList() As String, _
        ByVal cnt As Integer) As Boolean

        If cnt = 0 Then
            Return True
        End If

        For i As Integer = 0 To srcLineList.Length - 1
            If srcLineList(i).Trim() = "" Then
                Continue For
            End If
            srcLineList(i) = srcLineList(i).Substring(cnt)
        Next

        Return True

    End Function
#End Region

#End Region

#Region "変換対象の文字列を検索する正規表現を取得する。"
    ''' <summary>
    ''' 変換対象の文字列を検索する正規表現を取得する。
    ''' </summary>
    ''' <returns>正規表現</returns>
    ''' <remarks></remarks>
    Protected MustOverride Function GetRegEx() As Regex
#End Region

#Region "正規表現の検索結果を編集する。"
    ''' <summary>
    ''' 正規表現の検索結果を編集する。
    ''' </summary>
    ''' <param name="match">検索結果</param>
    ''' <returns>編集結果</returns>
    ''' <remarks></remarks>
    Protected MustOverride Function MatchEvaluator( _
        ByVal match As Match) As String
#End Region

#Region "予約語一覧を取得する。"
    ''' <summary>
    ''' 予約語一覧を取得する。
    ''' </summary>
    ''' <returns>予約語一覧</returns>
    ''' <remarks></remarks>
    Public MustOverride Function GetReservedWords() As String()
#End Region

#Region "タイトルを取得"
    ''' <summary>
    ''' タイトルを取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public MustOverride Function GetDefaultTitle() As String
#End Region

#Region "タイトルを取得"
    ''' <summary>
    ''' 前景色(タイトル)を取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public MustOverride Function GetTitleBackColor() As String
#End Region

#Region "背景色を取得"
    ''' <summary>
    ''' 背景色を取得
    ''' </summary>
    ''' <returns>背景色</returns>
    ''' <remarks></remarks>
    Public MustOverride Function GetBackColor() As String
#End Region

#Region "前景色を取得"
    ''' <summary>
    ''' 前景色を取得
    ''' </summary>
    ''' <returns>前景色</returns>
    ''' <remarks></remarks>
    Public MustOverride Function GetForeColor() As String
#End Region


End Class

[VB.NET]CodeConverterToHtml


[プログラムソース]
Imports System.Text.RegularExpressions
''' <summary>
''' 変換(C#ソースコード→HTML)
''' </summary>
''' <remarks></remarks>
Public Class CSharpCodeConverterToHtml
    Inherits CodeConverterToHtml

#Region "定数定義"
    ''' <summary>
    ''' 背景色
    ''' </summary>
    ''' <remarks></remarks>
    Private Const BACK_COLOR As String = "#FFFFE0"

    ''' <summary>
    ''' 背景色(タイトル)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const BACK_COLOR_TITLE As String = "#66CCCC"

    ''' <summary>
    ''' 前景色
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR As String = "#000000"

    ''' <summary>
    ''' 前景色(コメント)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR_COMMENT As String = "#008040"

    ''' <summary>
    ''' 前景色(文字列)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR_STRING As String = "#FF0000"

    ''' <summary>
    ''' 前景色(予約語)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR_RESERVED_WORD As String = "#0000FF"
#End Region

#Region "変数定義"
    ''' <summary>
    ''' 正規表現
    ''' </summary>
    ''' <remarks></remarks>
    Private m_RegEx As Regex = Nothing

    ''' <summary>
    ''' 予約語一覧
    ''' </summary>
    ''' <remarks></remarks>
    Private m_ReservedWords As New List(Of String)
#End Region

#Region "コンストラクタ"
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()

    End Sub
#End Region

#Region "変換対象の文字列を検索する正規表現を取得する。"
    ''' <summary>
    ''' 変換対象の文字列を検索する正規表現を取得する。
    ''' </summary>
    ''' <returns>正規表現</returns>
    ''' <remarks></remarks>
    Protected Overrides Function GetRegEx() As Regex
        If Not (Me.m_RegEx Is Nothing) Then
            Return Me.m_RegEx
        End If

        Dim strPatternAll As String = Nothing
        '正規表現パターン
        '※コメント判別
        '(先頭開始、0個以上の「&nbsp;」、1個以上の「//」、0個以上の任意文字)
        Dim strPattern1 As String = "^(&nbsp;)*(//)+.*"
        '※コメント判別
        '(先頭開始、0個以上の空白、1個以上の「//」、0個以上の任意文字)
        Dim strPattern2 As String = "^\s*(//)+.*"
        '※文字列判別
        '(「"」開始、0個以上の任意文字、最も手前の「"」終了)
        Dim strPattern3 As String = """.*?"""
        '※文字列判別
        '(「&quot;」開始、0個以上の任意文字、最も手前の「&quot;」終了)
        Dim strPattern4 As String = "&quot;.*?&quot;"
        '※予約語判別
        '(単語単位で予約語の何れかと同じ)
        Dim wkStr As String = String.Join("|", Me.GetReservedWords())
        Dim strPattern5 As String = "\b(" & wkStr & ")\b"

        strPatternAll = _
                    strPattern1 & "|" & strPattern2 & "|" & _
                    strPattern3 & "|" & strPattern4 & "|" & _
                    strPattern5

        Me.m_RegEx = New Regex(strPatternAll)

        Return Me.m_RegEx
    End Function
#End Region

#Region "正規表現の検索結果を編集する。"
    ''' <summary>
    ''' 正規表現の検索結果を編集する。
    ''' </summary>
    ''' <param name="match">検索結果</param>
    ''' <returns>編集結果</returns>
    ''' <remarks></remarks>
    Protected Overrides Function MatchEvaluator(ByVal match As Match) As String
        If match.Value.Replace("&nbsp;", "").StartsWith("//") OrElse _
            match.Value.Trim().StartsWith("//") Then
            'コメントの場合            
            Dim wk1 As Integer = match.Value.IndexOf("//")
            If wk1 = 0 Then
                Return String.Format( _
                    "<font color='{0}'>{1}</font>", _
                    FORE_COLOR_COMMENT, _
                    match.Value.Substring(wk1))
            End If
            Return match.Value.Substring(0, wk1) & _
                    String.Format( _
                    "<font color='{0}'>{1}</font>", _
                    FORE_COLOR_COMMENT, _
                    match.Value.Substring(wk1))
        End If

        If (match.Value.StartsWith("&quot;") AndAlso _
            match.Value.EndsWith("&quot;")) OrElse _
           (match.Value.StartsWith("""") AndAlso _
            match.Value.EndsWith("""")) Then
            '文字列の場合            
            Return String.Format( _
                "<font color='{0}'>{1}</font>", _
                FORE_COLOR_STRING, _
                match.Value)
        End If

        '予約語の場合
        Return String.Format( _
            "<font color='{0}'>{1}</font>", _
            FORE_COLOR_RESERVED_WORD, _
            match.Value)
    End Function
#End Region

#Region "予約語一覧を取得する。"
    ''' <summary>
    ''' 予約語一覧を取得する。
    ''' </summary>
    ''' <returns>予約語一覧</returns>
    ''' <remarks></remarks>
    Public Overrides Function GetReservedWords() As String()
        If Me.m_ReservedWords.Count > 0 Then
            Return Me.m_ReservedWords.ToArray()
        End If

        With Me.m_ReservedWords

            .AddRange(New String() {"abstract", "as", "base", "bool", "break"})
            .AddRange(New String() {"byte", "case", "catch", "char", "checked"})
            .AddRange(New String() {"class", "const", "continue", "decimal", "decimal"})
            .AddRange(New String() {"default", "delegate", "do", "double", "else"})
            .AddRange(New String() {"enum", "event", "explicit", "extern", "false"})
            .AddRange(New String() {"finally", "fixed", "float", "for", "foreach"})
            .AddRange(New String() {"from", "get", "goto", "group", "if"})
            .AddRange(New String() {"implicit", "in", "int", "interface", "internal"})
            .AddRange(New String() {"into", "is", "join", "let", "lock"})
            .AddRange(New String() {"long", "namespace", "new", "null", "object"})
            .AddRange(New String() {"operator", "orderby", "out", "override", "params"})
            .AddRange(New String() {"partial", "private", "protected", "public", "readonly"})
            .AddRange(New String() {"ref", "return", "sbyte", "sealed", "select"})
            .AddRange(New String() {"set", "short", "sizeof", "stackalloc", "static"})
            .AddRange(New String() {"string", "struct", "switch", "this", "throw"})
            .AddRange(New String() {"true", "try", "typeof", "uint", "ulong"})
            .AddRange(New String() {"unchecked", "unsafe", "ushort", "using", "value"})
            .AddRange(New String() {"virtual", "void", "volatile", "where", "while"})
            .AddRange(New String() {"yield"})

        End With

        Return Me.m_ReservedWords.ToArray()

    End Function
#End Region

#Region "タイトルを取得"
    ''' <summary>
    ''' タイトルを取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetDefaultTitle() As String
        Return "C#"
    End Function
#End Region

#Region "背景色(タイトル)を取得"
    ''' <summary>
    ''' 背景色(タイトル)を取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetTitleBackColor() As String
        Return BACK_COLOR_TITLE
    End Function
#End Region

#Region "背景色を取得"
    ''' <summary>
    ''' 背景色を取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetBackColor() As String
        Return BACK_COLOR
    End Function
#End Region

#Region "前景色を取得"
    ''' <summary>
    ''' 前景色を取得
    ''' </summary>
    ''' <returns>前景色</returns>
    ''' <remarks></remarks>
    Public Overrides Function GetForeColor() As String
        Return FORE_COLOR
    End Function
#End Region

End Class
[VB.NET]CSharpCodeConverterToHtml.vb


[プログラムソース]
Imports System.Text.RegularExpressions
''' <summary>
''' 変換(SQLServerコード→HTML)
''' </summary>
''' <remarks></remarks>
Public Class SqlServerCodeConverterToHtml
    Inherits CodeConverterToHtml

#Region "定数定義"
    ''' <summary>
    ''' 背景色
    ''' </summary>
    ''' <remarks></remarks>
    Private Const BACK_COLOR As String = "#FFFFE0"

    ''' <summary>
    ''' 背景色(タイトル)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const BACK_COLOR_TITLE As String = "#66CCCC"

    ''' <summary>
    ''' 前景色
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR As String = "#000000"

    ''' <summary>
    ''' 前景色(コメント)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR_COMMENT As String = "#008040"

    ''' <summary>
    ''' 前景色(文字列)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR_STRING As String = "#FF0000"

    ''' <summary>
    ''' 前景色(予約語)
    ''' </summary>
    ''' <remarks></remarks>
    Private Const FORE_COLOR_RESERVED_WORD As String = "#0000FF"
#End Region

#Region "変数定義"
    ''' <summary>
    ''' 正規表現
    ''' </summary>
    ''' <remarks></remarks>
    Private m_RegEx As Regex = Nothing

    ''' <summary>
    ''' 予約語一覧
    ''' </summary>
    ''' <remarks></remarks>
    Private m_ReservedWords As New List(Of String)
#End Region

#Region "コンストラクタ"
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()

    End Sub
#End Region

#Region "変換対象の文字列を検索する正規表現を取得する。"
    ''' <summary>
    ''' 変換対象の文字列を検索する正規表現を取得する。
    ''' </summary>
    ''' <returns>正規表現</returns>
    ''' <remarks></remarks>
    Protected Overrides Function GetRegEx() As Regex
        If Not (Me.m_RegEx Is Nothing) Then
            Return Me.m_RegEx
        End If

        Dim strPatternAll As String = Nothing
        '正規表現パターン
        '※コメント判別
        '(先頭開始、0個以上の「&nbsp;」、1個以上の「--」、0個以上の任意文字)
        Dim strPattern1 As String = "^(&nbsp;)*(--)+.*"
        '※コメント判別
        '(先頭開始、0個以上の空白、1個以上の「--」、0個以上の任意文字)
        Dim strPattern2 As String = "^\s*(--)+.*"
        '※文字列判別
        '(「'」開始、0個以上の任意文字、最も手前の「'」終了)
        Dim strPattern3 As String = "'.*?'"
        '※予約語判別
        '(単語単位で予約語の何れかと同じ)
        Dim wkStr As String = String.Join("|", Me.GetReservedWords())
        Dim strPattern4 As String = "\b(" & wkStr & ")\b"

        strPatternAll = _
                    strPattern1 & "|" & strPattern2 & "|" & _
                    strPattern3 & "|" & strPattern4 

        Me.m_RegEx = New Regex(strPatternAll, RegexOptions.IgnoreCase)

        Return Me.m_RegEx
    End Function
#End Region

#Region "正規表現の検索結果を編集する。"
    ''' <summary>
    ''' 正規表現の検索結果を編集する。
    ''' </summary>
    ''' <param name="match">検索結果</param>
    ''' <returns>編集結果</returns>
    ''' <remarks></remarks>
    Protected Overrides Function MatchEvaluator(ByVal match As Match) As String
        If match.Value.Replace("&nbsp;", "").StartsWith("--") OrElse _
            match.Value.Trim().StartsWith("--") Then
            'コメントの場合            
            Dim wk1 As Integer = match.Value.IndexOf("--")
            If wk1 = 0 Then
                Return String.Format( _
                    "<font color='{0}'>{1}</font>", _
                    FORE_COLOR_COMMENT, _
                    match.Value.Substring(wk1))
            End If
            Return match.Value.Substring(0, wk1) & _
                    String.Format( _
                    "<font color='{0}'>{1}</font>", _
                    FORE_COLOR_COMMENT, _
                    match.Value.Substring(wk1))
        End If

        If match.Value.StartsWith("'") AndAlso _
            match.Value.EndsWith("'") Then
            '文字列の場合            
            Return String.Format( _
                "<font color='{0}'>{1}</font>", _
                FORE_COLOR_STRING, _
                match.Value)
        End If

        '予約語の場合
        Return String.Format( _
            "<font color='{0}'>{1}</font>", _
            FORE_COLOR_RESERVED_WORD, _
            match.Value)
    End Function
#End Region

#Region "予約語一覧を取得する。"
    ''' <summary>
    ''' 予約語一覧を取得する。
    ''' </summary>
    ''' <returns>予約語一覧</returns>
    ''' <remarks></remarks>
    Public Overrides Function GetReservedWords() As String()
        If Me.m_ReservedWords.Count > 0 Then
            Return Me.m_ReservedWords.ToArray()
        End If

        With Me.m_ReservedWords

            .AddRange(New String() {"ADD", "ALL", "ALTER", "AND", "ANY"})
            .AddRange(New String() {"AS", "ASC", "AUTHORIZATION", "BACKUP", "BEGIN"})
            .AddRange(New String() {"BETWEEN", "BREAK", "BROWSE", "BULK", "BY"})
            .AddRange(New String() {"CASCADE", "CASE", "CHECK", "CHECKPOINT", "CLOSE"})
            .AddRange(New String() {"CLUSTERED", "COALESCE", "COLLATE", "COLUMN", "COMMIT"})
            .AddRange(New String() {"COMPUTE", "CONSTRAINT", "CONTAINS", "CONTAINSTABLE", "CONTINUE"})
            .AddRange(New String() {"CONVERT", "CREATE", "CROSS", "CURRENT", "CURRENT_DATE"})
            .AddRange(New String() {"CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "DATABASE"})
            .AddRange(New String() {"DBCC", "DEALLOCATE", "DECLARE", "DEFAULT", "DELETE"})
            .AddRange(New String() {"DENY", "DESC", "DISK", "DISTINCT", "DISTRIBUTED"})
            .AddRange(New String() {"DOUBLE", "DROP", "DUMP", "ELSE", "END"})
            .AddRange(New String() {"ERRLVL", "ESCAPE", "EXCEPT", "EXEC", "EXECUTE"})
            .AddRange(New String() {"EXISTS", "EXIT", "EXTERNAL", "FETCH", "FILE"})
            .AddRange(New String() {"FILLFACTOR", "FOR", "FOREIGN", "FREETEXT", "FREETEXTTABLE"})
            .AddRange(New String() {"FROM", "FULL", "FUNCTION", "GOTO", "GRANT"})
            .AddRange(New String() {"GROUP", "HAVING", "HOLDLOCK", "IDENTITY", "IDENTITY_INSERT"})
            .AddRange(New String() {"IDENTITYCOL", "IF", "IN", "INDEX", "INNER"})
            .AddRange(New String() {"INSERT", "INTERSECT", "INTO", "IS", "JOIN"})
            .AddRange(New String() {"KEY", "KILL", "LEFT", "LIKE", "LINENO"})
            .AddRange(New String() {"LOAD", "MERGE", "NATIONAL", "NOCHECK", "NONCLUSTERED"})
            .AddRange(New String() {"NOT", "NULL", "NULLIF", "OF", "OFF"})
            .AddRange(New String() {"OFFSETS", "ON", "OPEN", "OPENDATASOURCE", "OPENQUERY"})
            .AddRange(New String() {"OPENROWSET", "OPENXML", "OPTION", "OR", "ORDER"})
            .AddRange(New String() {"OUTER", "OVER", "PERCENT", "PIVOT", "PLAN"})
            .AddRange(New String() {"PRECISION", "PRIMARY", "PRINT", "PROC", "PROCEDURE"})
            .AddRange(New String() {"PUBLIC", "RAISERROR", "READ", "READTEXT", "RECONFIGURE"})
            .AddRange(New String() {"REFERENCES", "REPLICATION", "RESTORE", "RESTRICT", "RETURN"})
            .AddRange(New String() {"REVERT", "REVOKE", "RIGHT", "ROLLBACK", "ROWCOUNT"})
            .AddRange(New String() {"ROWGUIDCOL", "RULE", "SAVE", "SCHEMA", "SECURITYAUDIT"})
            .AddRange(New String() {"SELECT", "SEMANTICKEYPHRASETABLE", "SEMANTICSIMILARITYDETAILSTABLE"})
            .AddRange(New String() {"SEMANTICSIMILARITYTABLE", "SESSION_USER"})
            .AddRange(New String() {"SET", "SETUSER", "SHUTDOWN", "SOME"})
            .AddRange(New String() {"STATISTICS", "SYSTEM_USER", "TABLE"})
            .AddRange(New String() {"TABLESAMPLE", "TEXTSIZE", "THEN"})
            .AddRange(New String() {"TO", "TOP", "TRAN"})
            .AddRange(New String() {"TRANSACTION", "TRIGGER", "TRUNCATE"})
            .AddRange(New String() {"TRY_CONVERT", "TSEQUAL", "UNION"})
            .AddRange(New String() {"UNIQUE", "UNPIVOT", "UPDATE"})
            .AddRange(New String() {"UPDATETEXT", "USE", "USER"})
            .AddRange(New String() {"VALUES", "VARYING", "VIEW"})
            .AddRange(New String() {"WAITFOR", "WHEN", "WHERE"})
            .AddRange(New String() {"WHILE", "WITH", "WITHINGROUP", "WRITETEXT"})

        End With

        Return Me.m_ReservedWords.ToArray()

    End Function
#End Region

#Region "タイトルを取得"
    ''' <summary>
    ''' タイトルを取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetDefaultTitle() As String
        Return "SQLServer"
    End Function
#End Region

#Region "背景色(タイトル)を取得"
    ''' <summary>
    ''' 背景色(タイトル)を取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetTitleBackColor() As String
        Return BACK_COLOR_TITLE
    End Function
#End Region

#Region "背景色を取得"
    ''' <summary>
    ''' 背景色を取得
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetBackColor() As String
        Return BACK_COLOR
    End Function
#End Region

#Region "前景色を取得"
    ''' <summary>
    ''' 前景色を取得
    ''' </summary>
    ''' <returns>前景色</returns>
    ''' <remarks></remarks>
    Public Overrides Function GetForeColor() As String
        Return FORE_COLOR
    End Function
#End Region

End Class
[VB.NET]SqlServerCodeConverterToHtml

0 件のコメント:

コメントを投稿

[雑記]ドローン(DJI Mini 3)

(1)雑記 もともと多趣味の友人 masakazu Drone 氏が、 最近、 ドローン にハマり始めて、 更に、新たな趣味が増えたとのこと。 ドローン を始めてから、 まだ1年も経っていないとのことですが、 旅行先で山や川の景色を 空撮 して、 Youtube ...