...1-
...2|
...3|
...4|
...5|
...6|
...7|
...8|
...9|
..10|
..11|
..12|
..13|
..14|
..15|
..16|
..17|
..18|
..19|
..20-

..21
..22-
..23|
..24|
..25|
..26|
..27|
..28|
..29|
..30|
..31|
..32|
..33|
..34-

..35
..36
..37
..38
..39-
..40|
..41|
..42|
..43|
..44|
..45|-
..46||
..47||
..48||
..49||
..50||
..51||
..52||
..53||
..54||
..55||
..56||
..57|-

..58|
..59|-
..60||
..61||
..62||
..63||
..64||
..65||
..66||
..67||
..68||
..69||
..70||
..71||
..72||
..73||
..74||
..75||
..76||
..77||
..78||
..79||
..80|-

..81|
..82|
..83|-
..84||
..85||
..86||
..87||
..88||
..89||
..90||
..91||
..92||
..93||
..94||
..95||
..96||
..97||
..98||
..99||
.100||
.101||
.102||
.103||
.104||
.105||
.106|-

.107|
.108|
.109|-
.110||
.111||
.112||
.113||-
.114|||
.115|||
.116|||
.117|||
.118|||
.119|||
.120|||
.121|||
.122|||
.123|||
.124|||
.125|||
.126|||
.127|||
.128|||
.129|||
.130|||
.131|||
.132|||
.133|||
.134|||
.135|||
.136|||
.137|||
.138|||
.139|||
.140|||
.141|||
.142|||
.143|||
.144|||
.145|||
.146|||
.147|||
.148|||
.149|||
.150|||
.151|||
.152|||
.153|||
.154|||
.155|||
.156||-

.157||
.158||
.159||-
.160|||
.161|||
.162|||
.163|||
.164|||
.165|||
.166|||
.167|||
.168|||
.169|||
.170|||
.171|||
.172|||
.173|||
.174|||
.175|||
.176|||
.177|||
.178|||
.179|||
.180|||
.181|||
.182|||
.183|||
.184|||
.185|||
.186|||
.187|||
.188|||
.189|||
.190|||
.191|||
.192|||
.193|||
.194|||
.195||-

.196||
.197||
.198||
.199||
.200||
.201|-

.202|
.203|-
.204||
.205||
.206||
.207||
.208||
.209||
.210||
.211||
.212||
.213||
.214||
.215||
.216||
.217||
.218||
.219||
.220||
.221||
.222||
.223||
.224||
.225||
.226||
.227||
.228||
.229||
.230||
.231||
.232||
.233||
.234||
.235||
.236||
.237||
.238|-

.239|
.240|
.241|-
.242||
.243||
.244||
.245||
.246||
.247||
.248||
.249||
.250||
.251||
.252||
.253||
.254||
.255||
.256||
.257||
.258|-

.259|
.260|-
.261||
.262||
.263||
.264||
.265||
.266||
.267||
.268||
.269||
.270|-

.271|
.272|-
.273||
.274||
.275||
.276||
.277||
.278||
.279||
.280||
.281||
.282||
.283||
.284||
.285||
.286|-

.287|
.288|-
.289||
.290||
.291||
.292||
.293||
.294||
.295||
.296||
.297||
.298||
.299||-
.300|||
.301|||
.302|||
.303|||
.304||-

.305||
.306||
.307||-
.308|||
.309|||
.310||-

.311||
.312||-
.313|||
.314|||
.315||-

.316||
.317||-
.318|||
.319|||
.320||-

.321||
.322||
.323||-
.324|||
.325|||
.326|||
.327|||
.328|||
.329|||
.330|||
.331|||
.332|||
.333|||
.334|||
.335|||
.336|||
.337|||
.338|||-
.339||||
.340||||
.341||||
.342||||
.343||||
.344||||
.345||||
.346||||
.347||||
.348||||
.349||||
.350||||
.351||||
.352||||
.353||||
.354||||
.355||||
.356||||
.357||||
.358||||
.359||||
.360||||
.361||||
.362||||
.363||||
.364||||
.365||||
.366||||
.367||||
.368||||
.369||||
.370||||
.371||||
.372|||-

.373|||
.374|||-
.375||||
.376||||
.377||||
.378||||
.379||||
.380||||
.381||||
.382||||
.383||||
.384||||
.385||||
.386||||
.387||||
.388||||
.389||||
.390|||-

.391|||
.392|||-
.393||||
.394||||
.395||||
.396||||
.397||||
.398||||
.399||||
.400||||
.401||||
.402||||
.403||||
.404||||
.405||||
.406||||
.407|||-

.408|||
.409|||
.410|||
.411|||
.412|||
.413|||
.414|||
.415|||
.416|||
.417|||
.418|||
.419|||
.420||-

.421||
.422||-
.423|||
.424|||
.425||-

.426||
.427||-
.428|||
.429|||
.430|||
.431|||
.432|||
.433|||
.434|||
.435|||
.436|||
.437|||
.438|||
.439|||
.440|||
.441|||
.442||-

.443||
.444||-
.445|||
.446|||
.447|||
.448|||
.449|||
.450|||
.451|||
.452|||
.453|||
.454|||
.455|||
.456|||
.457|||
.458|||
.459|||
.460||-

.461||
.462||-
.463|||
.464|||
.465||-

.466||
.467|-

.468|
.469|-
.470||
.471||
.472||
.473||
.474||
.475||
.476||
.477||-
.478|||
.479|||
.480|||
.481|||
.482|||
.483|||
.484|||
.485|||
.486|||
.487|||
.488|||
.489|||
.490|||
.491|||
.492|||
.493|||
.494|||
.495|||
.496|||
.497|||
.498|||
.499|||
.500||-

.501||
.502|-

.503|
.504-
.505|
.506|
.507|
.508|
.509|
.510|
.511-

.512|
.513|-
.514||
.515||
.516||
.517||
.518||
.519||
.520||
.521||
.522||
.523||
.524||
.525||
.526||
.527||
.528||
.529||
.530||
.531||
.532||
.533||
.534||
.535||
.536||
.537||
.538||
.539||
.540||
.541||
.542||
.543||
.544||
.545||
.546||
.547||
.548||
.549||
.550||
.551||
.552||
.553||
.554||
.555||
.556||
.557||
.558||
.559||
.560||
.561|-

.562-
.563|
.564|
.565|
.566|
.567-

.568|
.569|-
.570||
.571||
.572||
.573||
.574||
.575||
.576||
.577||
.578||
.579||
.580||
.581||
.582||
.583||
.584||
.585||
.586||
.587||
.588||
.589||
.590||
.591||
.592||
.593||
.594||
.595||
.596|-

.597|
.598|
.599-

.600
.601-
.602|
.603|
.604|
.605|-
.606||
.607||
.608|-

.609|
.610|-
.611||
.612|-

.613|
.614|-
.615||
.616|-

.617-

.618
.619
/* CharMY.CodeToHtml CodeToHtmlConverter
 * 
 * COPYLEFT (C) CharMY 2012-2013 Yanagihara Masami
 * 
 * 
 * This program is free software: you can redistribute it and/or modify   *
 * it under the terms of the GNU General Public License as published by   *
 * the Free Software Foundation, either version 3 of the License, or      *
 * (at your option) any later version.                                    *
 *                                                                        *
 * This program is distributed in the hope that it will be useful,        *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 * GNU General Public License for more details.                           *
 *                                                                        *
 * You should have received a copy of the GNU General Public License      *
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 * 
 * 
 */


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using CharMY.Arithmetic;
using CharMY.ComponentModel;
using CharMY.IO;
using CharMY.Net;
using CharMY.Numerics;
using CharMY.Text;


namespace CharMY.CodeToHtml
{
    public class CodeToHtmlConverter : CharMYCore.NonElement
    {
        public bool ShowCollapceLevel { getset; }
        public string CssFileName { getset; }
        public string ScriptFileName { getset; }
        private readonly ReadOnlyCollection<SettingToCssConverter> _css;
        public CodeToHtmlConverter(string classNameparams VSEditorVersion[] version)
        {
            ShowCollapceLevel = true;
            CssFileName = null;
            ScriptFileName = null;

            if (version == null || version.Length == 0)
                version = new[] { VSEditorVersion.VS2010ExpressCSharp };

            _css = version
                .Select(v => new SettingToCssConverter(classNamev))
                .ToArray()
                .ToReadOnlyCollection();
        
}

        #region const tags

        private const string
            __spliter = "@@",
            __indicator = "\",
            __indicator_begin = __indicator + "_begin",
            __indicator_end = __indicator + "_end",
            __indicator_break = __indicator + "_break",
            __indicator_spliter = __indicator + "_spliter",
            __text_color_header = "\\cf",
            __color_header = "\\colortbl",
            __color_header_r = "\\red",
            __color_header_g = "\\green",
            __color_header_b = "\\blue",
            __class_header_begin = @"<code class=""",
            __class_header_end = @""">",
            __break_node = @"<br>";

        protected const string
            ClassFooter = "</code>";

        
#endregion

        private static string MakeRtfText(string rtfSource)
        {
            NumberFormat _format = null;
            Encoding _encode = null;
            var format = TypeInference.Func(() => _format ?? (_format = NumberFormats.Hex()));
            var encode = TypeInference.Func(() => _encode ?? (_encode = rtfSource
                .AllMatchOf(@"\\ansicpg([0-9]+)")
                .Select(m => Encoding.GetEncoding(m.Groups[1].Value.To(0)))
                .FirstOrDefault(Encoding.Default)
            ));

            rtfSource = rtfSource
                .ReplaceByRegex(@"\\'([0-9a-fA-F]+)"m =>
                {
                    var bytes = (m.Groups[1].Value.To(0format()) & 0xFFFF).ToExInt().ToByteArray();
                    var result = new string(encode().GetChars(bytes));
                    return result;
                })
                .ReplaceByRegex(@"\\uc1\\u((-|)[0-9]+)\?"m =>
                {
                    var result = ((char)m.Groups[1].Value.To(0)).ToString();
                    return result;
                });
            return rtfSource;
        
}

        protected IEnumerable<string> MakeHtmlCore(string rtfSourceSettingToCssConverter css)
        {
            Checker.ArgumentNotNull(css);

            var nodes = new Queue<string[]>();
            #region sprit

            var rtf = MakeRtfText(rtfSource)
                .Replace("\\\\"__indicator)
                .Replace("\\{"__indicator_begin)
                .Replace("\\}"__indicator_end)
                .Replace("\r""")
                .Replace("\\par\n"__indicator_break)
                .ReplaceByRegex(@" *\\par "__indicator_break)
                .Replace(__spliter__indicator_spliter);

            var regex = StringExtensions.Regex(@"\{([^\{\}]+)\}");
            bool @continue = true;
            while (@continue)
            {
                @continue = false;
                rtf = regex.Replace(rtfm =>
                {
                    var items = m.Groups[1].Value
                        .Split(__spliterStringSplitAdditionalOptions.SeparateBefore);
                    foreach (var item in items)
                        nodes.Enqueue(item
                            .Split("\\"StringSplitAdditionalOptions.SeparateBefore)
                            .Where(inner => inner.Length > 0)
                            .ToArray()
                        );
                    @continue = true;
                    return __spliter;
                });
            }

#if WRITE_INFO
            Console.WriteLine();
            foreach (var items in nodes)
            {
                Console.WriteLine("@");
                foreach (var item in items)
                {
                    Console.WriteLine("       >" + item + "<");
                }
            }
#endif

            
#endregion

            var colors = new List<string>();
            #region search colors
            {
                colors.Add(ToHtmlHeader(css.NameOfDefault));

                var color_node = nodes
                    .FirstOrDefault(items => items.Length >= 4 && items[0].StartsWith(__color_header));
                int rgb;
                r = g = b = 0;
                if (color_node != null)
                    foreach (var item in color_node
                        .Skip(1)
                        .ZipKey(item => item.MatchOf("[0-9]+").Value.To(-1))
                        .Where(pair => pair.Key >= 0))
                    {
                        if (item.Value.StartsWith(__color_header_r))
                            r = item.Key;

                        else if (item.Value.StartsWith(__color_header_g))
                            g = item.Key;

                        else if (item.Value.StartsWith(__color_header_b))
                            b = item.Key;

                        if (item.Value.EndsWith(";"))
                        {
                            var color_class = css.ColorClass(rgb);
                            colors.Add(color_class);
                        }
                    }
            }

#if WRITE_INFO
            for (int i = 0 ; i < colors.Count ; ++i)
                Console.WriteLine(i + "    " + colors[i]);
#endif

            
#endregion

            var last_node = nodes.LastOrDefault();
            return this.MakeHtmlCore(colorslast_nodecss)
                .ToSingleString()
                .Split("<br>"StringSplitAdditionalOptions.None);
        
}
        private IEnumerable<string> MakeHtmlCore(List<string> colorsstring[] nodeSettingToCssConverter css)
        {
            string node_class = ToHtmlHeader(css.NameOfDefault);
            string node_text = "";
            foreach (var item in node.Where(item => !item.StartsWith(__spliter)))
            {
                if (item.StartsWith(__text_color_header))
                {
                    if (node_text.Length > 0)
                        yield return this.ToHtml(node_classnode_text);
                    node_text = "";

                    var color_index = item.MatchOf("[0-9]+").Value.To(-1);
                    if (0 <= color_index && color_index < colors.Count)
                    {
                        node_class = ToHtmlHeader(colors[color_index]);
                    }
                    else
                    {
                        node_class = ToHtmlHeader(css.NameOfDefault);
                    }
                }
                {
                    var text = item
                        .ReplaceByRegex(@"\\[a-z]+[0-9]*( |<br>|\\|)"m =>
                        {
                            if (!string.IsNullOrWhiteSpace(m.Groups[1].Value))
                                return m.Groups[1].Value;
                            return "";
                        });
                    node_text += text;
                }
            }

            if (node_text.Length > 0)
                yield return this.ToHtml(node_classnode_text);
        
}
        private static string ToHtmlHeader(string name) { return __class_header_begin + name + __class_header_end; }
        protected string ToHtml(string nodeClassstring nodeText)
        {
            var class_head = nodeClass;
            nodeText = nodeText
                .RepalceToHtml()
                .Replace(__indicator_spliter__spliter)
                .Replace(__indicator_begin"{")
                .Replace(__indicator_end"}")
                .Replace(__indicator_break__break_node)
                .Replace(__indicator"\\");
            nodeText = class_head
                + nodeText.ReplaceByRegex(__break_nodem => ClassFooter + __break_node + nodeClass)
                + ClassFooter;

            nodeText = nodeText
                .ReplaceByRegex(__class_header_begin + @"[^""]+" + __class_header_end + ClassFooter"");

            return nodeText;
        
}
        protected virtual IEnumerable<string> MakeLineNumbers(SettingToCssConverter css)
        {
            var nums = Sequence
                .For(1i => truei => i + 1)
                .ToStrings()
                .Select(num =>
                    ToHtmlHeader(css.NameOfSpace+ '.'.Repeat(4 - num.Length+ ClassFooter
                    + ToHtmlHeader(css.NameOfLineNumber+ num + ClassFooter
                    + ToHtmlHeader(css.NameOfLineSeparator+ "|" + ClassFooter);

            return nums;
        
}
        protected static string GetNodeClassName(string nodeHeader)
        {
            if (nodeHeader.StartsWith(__class_header_begin))
            {
                int name_length = nodeHeader
                    .IndexOf('"'__class_header_begin.Length- __class_header_begin.Length;
                if (name_length > 0)
                {
                    var name = nodeHeader
                        .Substring(__class_header_begin.Lengthname_length);

                    return name;
                }
            }
            return null;
        
}

        #region make collapse blocks and line numbers

        protected static string
            RegexSpace = "(" + " ".RepalceToHtml() + ")",
            RegexClassHead = "<code [^>]+>",
            RegexSpaceAny = "(" + RegexClassHead + RegexSpace + "*)",
            RegexSpace4Or8 = RegexClassHead + "(" + RegexSpace + "{4}){1,2}",
            BlockKey = "blockkey",
            LineBlockKey = "linekey";

        protected static string ToRegexBlock(string beginKey)
        {
            var result =
                "(" + ClassFooter + RegexClassHead + "|)"
                + "(?<" + BlockKey + ">" + beginKey + ").*" + ClassFooter;
            return result;
        
}

        protected virtual IEnumerable<string> GetBlockBeginRegexs()
        {
            yield return RegexSpaceAny + ToRegexBlock(@"#region(" + ClassFooter + RegexClassHead + @"|)[&;0-9a-zA-Z]+");
            yield return RegexSpace4Or8 + ToRegexBlock(@"\{");
        
}
        protected virtual IEnumerable<string> GetBlockEndRegexs()
        {
            yield return RegexSpaceAny + ToRegexBlock(@"#endregion");
            yield return RegexSpace4Or8 + ToRegexBlock(@"\}");
        
}
        protected virtual IEnumerable<string> GetLinesBlockRegexs()
        {
            yield return RegexSpaceAny + ToRegexBlock(@"(?<" + LineBlockKey + @">using|//)");
            yield return __class_header_begin + "(?<" + LineBlockKey + @">[^PS""]+)" + __class_header_end + "[^<>]+" + ClassFooter + "$";
        
}

        private string[] MakeLinesAndBlocks(string[] codeSettingToCssConverter cssout IEnumerable<string> lines)
        {
            var lines_array = this.MakeLineNumbers(css)
                .Take(code.Length)
                .ToArray();

            var reg_comment = this.GetLinesBlockRegexs().ToArray();
            var reg_begin = this.GetBlockBeginRegexs().ToArray();
            var reg_end = this.GetBlockEndRegexs().ToArray();

            var _collapse_index = 0;
            var collapse_indexes = new Stack<int>();
            int comment_line_count = 0;
            Match comment_begin_match = null;
            for (int i = 0 ; i < code.Length ; ++i)
            {
                #region comment match
                {
                    var match = reg_comment
                        .SelectMany(reg => code[i].AllMatchOf(reg))
                        .FirstOrDefault();
                    if (match != null && match.Index == 0 && match.Groups[LineBlockKey!= null)
                    {
                        if (comment_begin_match == null)
                        {
                            comment_line_count = 0;
                            comment_begin_match = match;
                        }
                        if (match.Groups[LineBlockKey].Value == comment_begin_match.Groups[LineBlockKey].Value)
                        {
                            ++comment_line_count;
                            continue;
                        }
                    }

                    if (comment_line_count >= 2)
                    {
                        var i_begin = i - comment_line_count;
                        var i_end = i - 1;
                        ++_collapse_index;
                        CollapseBegin(ref code[i_begin], ref lines_array[i_begin], comment_begin_match_collapse_indexcss);
                        CollapseEnd(ref code[i_end], ref lines_array[i_end], null_collapse_indexcss);
                    }

                    if (comment_begin_match != null)
                    {
                        comment_line_count = 0;
                        comment_begin_match = null;
                    }
                }
                
#endregion

                #region block begin
                {
                    var match = reg_begin
                        .SelectMany(reg => code[i].AllMatchOf(reg))
                        .FirstOrDefault();
                    if (match != null && match.Index == 0)
                    {
                        collapse_indexes.Push(++_collapse_index);
                        this.CollapseLevelSet(ref lines_array[i], collapse_indexes.Count);
                        CollapseBegin(ref code[i], ref lines_array[i], matchcollapse_indexes.Peek(), css);

                        comment_line_count = 0;
                        comment_begin_match = null;
                        continue;
                    }
                }
                
#endregion

                #region block end
                {
                    var match = reg_end
                        .SelectMany(reg => code[i].AllMatchOf(reg))
                        .FirstOrDefault();
                    if (match != null && match.Index == 0)
                    {
                        this.CollapseLevelSet(ref lines_array[i], collapse_indexes.Count);
                        CollapseEnd(ref code[i], ref lines_array[i], matchcollapse_indexes.Pop(), css);

                        comment_line_count = 0;
                        comment_begin_match = null;
                        continue;
                    }
                }
                
#endregion

                this.CollapseLevelSet(ref lines_array[i], collapse_indexes.Count);
            }

            int last = code.Length - 1;
            while (collapse_indexes.Count > 0)
            {
                CollapseEnd(ref code[last], ref lines_array[last], nullcollapse_indexes.Pop(), css);
            }

            lines = lines_array;
            return code;
        
}
        protected void CollapseLevelSet(ref string lineint level)
        {
            if (this.ShowCollapceLevel)
                line = line.Replace("|"Enumerable.Repeat("|"level).ToSingleString());
        
}
        private static void CollapseBegin(ref string coderef string lineMatch matchint indexSettingToCssConverter css)
        {
            int insert_index = code.Length;
            if (match != null && match.Groups[BlockKey].Length > 0)
            {
                var group = match.Groups[BlockKey];
                insert_index = code.IndexOf(ClassFootergroup.Index + group.Length);
                insert_index = (insert_index < 0? code.Length : (insert_index + ClassFooter.Length);
            }

            var span = @"<span class=""collapse" + index + @""">";
            code = code.Insert(insert_indexspan);
            line = line
                .Replace(
                    "|" + ClassFooter,
                    ClassFooter + CollapseLineItem(indexcsstrue+ span);
        
}
        private static void CollapseEnd(ref string coderef string lineMatch matchint indexSettingToCssConverter css)
        {
            int insert_index = code.Length;
            if (match != null && match.Groups[BlockKey].Length > 0)
            {
                var group = match.Groups[BlockKey];
                insert_index = group.Index;
            }

            var span = @"</span>";
            code = code.Insert(insert_indexspan);
            line = line
                .Replace(
                    "|" + ClassFooter,
                    ClassFooter + CollapseLineItem(indexcssfalse)
                )
                + span;
        
}
        private static string CollapseLineItem(int indexSettingToCssConverter cssbool begin)
        {
            var result = ToHtmlHeader(begin ? css.NameOfLineCollapse : css.NameOfLineCollapseEnd+ @"- <!-- collapse" + index + @" -->" + ClassFooter;
            return result;
        
}

        
#endregion

        #region make link

        private static string
            __color_name = "colorname",
            __class_name = "classname",
            __reg_link_class = @"<code class=""(?<" + __color_name + @">"
                + SettingToCssConverter.__link_names + @")"">(?<" + __class_name + @">[ _A-Za-z0-9]+)" + ClassFooter;
        private void MakeLinks(string[] codeFileInfo saveTarget)
        {
            if (saveTarget == null)
                return;

            var files = saveTarget.Directory
                .GetFiles("*.html"SearchOption.TopDirectoryOnly)
                .Where(file => file.Name.Length > 0 && Char.IsLetter(file.Name[0]) && !saveTarget.PathEquals(file))
                .SelectMany(file => file.NameWithoutExtension().Split('-').ZipValue(_ => file))
                .ToDictionary();

            for (int i = 0 ; i < code.Length ; ++i)
            {
                code[i= code[i]
                    .ReplaceByRegex(__reg_link_classm =>
                    {
                        if (!files.ContainsKey(m.Groups[__class_name].Value))
                            return m.Value;

                        var result = @"<a class=""" + m.Groups[__color_name].Value + @""" href=""./" + files[m.Groups[__class_name].Value].Name + @""">"
                            + m.Value + @"</a>";
                        return result;
                    });
            }
        
}

        
#endregion

        /// <summary>
        /// Output html file with css style-sheet file and javaScript file.
        /// </summary>
        /// <param name="saveTarget">saving html file</param>
        /// <param name="rtfSource">rich text source</param>
        /// <param name="setting">C# setting file</param>
        /// <param name="useCss">if true, output css file, else write style code in html.</param>
        /// <returns>html core node</returns>

        public string SaveHtmlFile(FileInfo saveTargetstring rtfSourceFileInfo setting = nullbool useCss = true)
        {
            if (saveTarget == null || rtfSource == null)
                return null;

            var cssFile = saveTarget.ChangeName((nameext=> (this.CssFileName ?? name+ ".css");
            var scriptFile = saveTarget.ChangeName((nameext=> (this.ScriptFileName ?? name+ ".js");
            var css_link = @"
<link rel=""stylesheet"" type=""text/css"" href=""./" + cssFile.Name + @""" media=""all"" />
<script type=""text/javascript"" src=""./" + scriptFile.Name + @"""></script>
";

            var result = this
                .MakeHtmlAndCss(rtfSourcesettingsaveTarget)
                .OrderByDescending(tuple => tuple.Item1.AllRangeOf(SettingToCssConverter.UndefinedName).Count())
                .FirstOrDefault();
            if (!useCss)
            {
                scriptFile = null;
                cssFile = null;
                css_link = @"
<style>" + result.Item2 + @"    </style>
<script type=""text/javascript"">" + CollapceJavaScript.Code + @"</script>
";
            }

            var htmlText = @"
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv=""Content-Type"" content=""text/html; charset=" + result.Item3.Encoding.WebName.ToLower() + @""" />
    <meta http-equiv=""Content-Style-Type"" content=""text/css"" />
    " + css_link + @"
</head>
<body>

" + result.Item1 + @"

</body>
";

            var io = Files.Text(result.Item3.Encoding).Base;
            io.Save(saveTargethtmlText);
            if (cssFile != null)
                io.Save(cssFileresult.Item2);
            if (scriptFile != null)
                io.Save(scriptFileCollapceJavaScript.Code);

            return result.Item1;
        
}
        /// <summary>
        /// Make html and css.
        /// </summary>
        /// <param name="rtfSource">rich text source</param>
        /// <param name="setting">C# setting file</param>
        /// <returns>key = css, value = html core node</returns>

        public IEnumerable<Tuple<stringstringSettingToCssConverter>> MakeHtmlAndCss(string rtfSourceFileInfo setting = nullFileInfo saveTarget = null)
        {
            foreach (var css in _css)
            {
                Console.WriteLine("check " + css);

                var cssText = css.MakeCss(setting);
                var core = this.MakeHtmlCore(rtfSourcecss).ToArrayCast();
                IEnumerable<string> lines;
                var code = this.MakeLinesAndBlocks(corecssout lines);

                this.MakeLinks(codesaveTarget);

                var htmlText = @"
<div class=""" + css.ClassName + @""">
" +

                (lines == null ? "" : @"<div class=""" + css.ClassNameLineNumber + @""">" + lines
                    .Take(code.Length)
                    .ToSingleString(__break_node+ @"</div>")

+ @"
<div class=""" + css.ClassNameCode + @""">" + code.Select(c => c ?? "").ToSingleString(__break_node+ @"</div>

</div>";
                var result = Tuple.Create(htmlTextcssTextcss);
                yield return result;
            }
        
}

        public override string ToString() { return "html"; }
    
}
    public class VBCodeToHtmlConverter : CodeToHtmlConverter
    {
        public VBCodeToHtmlConverter(params VSEditorVersion[] version) : base("vbcode"version) { }

        protected override IEnumerable<string> GetBlockBeginRegexs()
        {
            yield return RegexSpaceAny + ToRegexBlock(@"Sub");
            yield return RegexSpaceAny + ToRegexBlock(@"Func");
        
}
        protected override IEnumerable<string> GetBlockEndRegexs()
        {
            yield return RegexSpaceAny + ToRegexBlock(@"End");
        
}
        protected override IEnumerable<string> GetLinesBlockRegexs()
        {
            yield return RegexSpaceAny + ToRegexBlock(@"Using|'");
        
}
    
}
}