PageRenderTime 35ms CodeModel.GetById 19ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/BlogEngine.NET/App_Code/Extensions/SyntaxHighlighter.cs

#
C# | 299 lines | 234 code | 47 blank | 18 comment | 39 complexity | 508e93dadcfbc8bde742edc73dedd9d6 MD5 | raw file
  1using System.Text;
  2using System.Web;
  3using System.Web.UI.HtmlControls;
  4using BlogEngine.Core;
  5using BlogEngine.Core.Web.Controls;
  6using BlogEngine.Core.Web.Extensions;
  7using Page=System.Web.UI.Page;
  8using System.Collections.Generic;
  9using System;
 10
 11[Extension("Adds <a target=\"_new\" href=\"http://alexgorbatchev.com/wiki/SyntaxHighlighter\">Alex Gorbatchev's</a> source code formatter", "2.5.1", "<a target=\"_new\" href=\"http://dotnetblogengine.net/\">BlogEngine.NET</a>")]
 12public class SyntaxHighlighter
 13{
 14    #region Private members
 15    private const string ExtensionName = "SyntaxHighlighter";
 16    static protected Dictionary<Guid, ExtensionSettings> _blogsOptions = new Dictionary<Guid, ExtensionSettings>();
 17    static protected Dictionary<Guid, ExtensionSettings> _blogsThemes = new Dictionary<Guid, ExtensionSettings>();
 18    #endregion
 19
 20    /// <summary>
 21    ///     The sync root.
 22    /// </summary>
 23    private static readonly object syncRoot = new object();
 24
 25    private static ExtensionSettings Options
 26    {
 27        get
 28        {
 29            Guid blogId = Blog.CurrentInstance.Id;
 30            ExtensionSettings options = null;
 31            _blogsOptions.TryGetValue(blogId, out options);
 32
 33            if (options == null)
 34            {
 35                lock (syncRoot)
 36                {
 37                    _blogsOptions.TryGetValue(blogId, out options);
 38
 39                    if (options == null)
 40                    {
 41                        // Initializes
 42                        //   (1) Options
 43                        //   (3) Themees
 44                        // for the current blog instance.
 45
 46                        // options
 47                        options = new ExtensionSettings("Options");
 48                        options.IsScalar = true;
 49                        options.Help = OptionsHelp();
 50
 51                        options.AddParameter("cdnScriptsPath", "CDN Script Path", 250, false);
 52                        options.AddParameter("cdnStylesPath", "CDN Styles Path", 250, false);
 53                        options.AddParameter("gutter", "Gutter");
 54                        options.AddParameter("smart-tabs", "Smart tabs");
 55                        options.AddParameter("auto-links", "Auto links");
 56                        options.AddParameter("collapse", "Collapse");
 57                        options.AddParameter("tab-size", "Tab size");
 58                        options.AddParameter("toolbar", "Toolbar");
 59
 60                        options.AddValue("cdnScriptsPath", "http://alexgorbatchev.com.s3.amazonaws.com/pub/sh/3.0.83/scripts/");
 61                        options.AddValue("cdnStylesPath", "http://alexgorbatchev.com.s3.amazonaws.com/pub/sh/3.0.83/styles/");
 62                        options.AddValue("gutter", true);
 63                        options.AddValue("smart-tabs", true);
 64                        options.AddValue("auto-links", true);
 65                        options.AddValue("collapse", false);
 66                        options.AddValue("tab-size", 4);
 67                        options.AddValue("toolbar", true);
 68
 69                        _blogsOptions[blogId] = ExtensionManager.InitSettings(ExtensionName, options);
 70
 71                        // themes
 72                        ExtensionSettings themes = new ExtensionSettings("Themes");
 73                        themes.IsScalar = true;
 74                        themes.AddParameter("SelectedTheme", "Themes", 20, false, false, ParameterType.ListBox);
 75                        themes.AddValue("SelectedTheme", new string[] { "Default", "Django", "Eclipse", "Emacs", "FadeToGrey", "MDUltra", "Midnight", "Dark" }, "Default");
 76                        _blogsThemes[blogId] = ExtensionManager.InitSettings(ExtensionName, themes);
 77                    }
 78                }
 79            }
 80
 81            return options;
 82        }
 83    }
 84
 85    private static ExtensionSettings Themes
 86    {
 87        get
 88        {
 89            // by invoking the "Options" property getter, we are ensuring
 90            // that an entry is put into _blogsThemes for the current blog instance.
 91            ExtensionSettings options = Options;
 92            return _blogsThemes[Blog.CurrentInstance.Id];
 93        }
 94    }
 95
 96    static SyntaxHighlighter()
 97    {
 98        Post.Serving += AddSyntaxHighlighter;
 99        InitSettings();
100    }
101
102    private static void AddSyntaxHighlighter(object sender, ServingEventArgs e)
103    {
104        if (!ExtensionManager.ExtensionEnabled("SyntaxHighlighter"))
105            return;
106
107		if(e.Location == ServingLocation.Feed) 
108            return;
109
110        // if no code blocks on the page - don't bother
111        if (!e.Body.ToLowerInvariant().Contains("<pre class=\"brush:"))
112            return;
113	
114        HttpContext context = HttpContext.Current;
115		
116        Page page = (Page)context.CurrentHandler;
117
118        if ((context.CurrentHandler is Page == false) || (context.Items[ExtensionName] != null))
119        {
120            return;
121        }
122
123        AddCssStyles(page);
124        AddJavaScripts(page);
125        AddOptions(page);
126
127        context.Items[ExtensionName] = 1;
128    }
129
130    private static void AddCssStyles(Page page)
131    {
132        AddStylesheet("shCore.css", page);
133
134        if (Themes != null)
135        {
136            switch (Themes.GetSingleValue("SelectedTheme"))
137            {
138                case "Django":
139                    AddStylesheet("shThemeDjango.css", page);
140                    break;
141                case "Eclipse":
142                    AddStylesheet("shThemeEclipse.css", page);
143                    break;
144                case "Emacs":
145                    AddStylesheet("shThemeEmacs.css", page);
146                    break;
147                case "FadeToGrey":
148                    AddStylesheet("shThemeFadeToGrey.css", page);
149                    break;
150                case "MDUltra":
151                    AddStylesheet("shThemeMDUltra.css", page);
152                    break;
153                case "Midnight":
154                    AddStylesheet("shThemeMidnight.css", page);
155                    break;
156                case "Dark":
157                    AddStylesheet("shThemeRDark.css", page);
158                    break;
159                default:
160                    AddStylesheet("shThemeDefault.css", page);
161                    break;
162            }
163        }       
164    }
165
166    private static void AddJavaScripts(Page page)
167    {
168        AddJavaScript("shCore.js", page);
169        AddJavaScript("shAutoloader.js", page);
170
171        // register starter script
172        page.ClientScript.RegisterStartupScript(page.GetType(), "shInit.js", 
173            String.Format("<script type=\"text/javascript\" src=\"{0}\"></script>", GetUrl("Scripts/syntaxhighlighter/", "shInit.js")));
174    }
175
176    #region Script/Style adding
177
178    private static void AddJavaScript(string src, Page page)
179    {
180        page.ClientScript.RegisterStartupScript(page.GetType(), src, String.Format("<script type=\"text/javascript\" src=\"{0}\"></script>", GetUrl(ScriptsFolder(), src)));
181    }
182
183    private static void AddStylesheet(string href, Page page)
184    {
185        HtmlLink css = new HtmlLink();
186        css.Attributes["type"] = "text/css";
187        css.Attributes["rel"] = "stylesheet";
188        css.Attributes["href"] = GetUrl(StylesFolder(), href);
189        page.Header.Controls.Add(css);
190    }
191
192    private static void AddOptions(Page page)
193    {
194        StringBuilder sb = new StringBuilder();
195        
196        sb.AppendLine("<script type=\"text/javascript\" defer=\"defer\">");
197
198        // add not-default options
199        if (Options != null)
200        {
201            if(Options.GetSingleValue("gutter").ToLowerInvariant() == "false")
202                sb.AppendLine(GetOption("gutter"));
203
204            if (Options.GetSingleValue("smart-tabs").ToLowerInvariant() == "false")
205                sb.AppendLine(GetOption("smart-tabs"));
206
207            if (Options.GetSingleValue("auto-links").ToLowerInvariant() == "false")
208                sb.AppendLine(GetOption("auto-links"));
209
210            if (Options.GetSingleValue("collapse").ToLowerInvariant() == "true")
211                sb.AppendLine(GetOption("collapse"));
212            
213            if (Options.GetSingleValue("toolbar").ToLowerInvariant() == "false")
214                sb.AppendLine(GetOption("toolbar"));
215
216            if (Options.GetSingleValue("tab-size") != "4")
217                sb.AppendLine(GetOption("tab-size"));
218
219            // depricated in latest version
220            //sb.AppendLine(GetOption("light"));
221            //sb.AppendLine(GetOption("wrap-lines"));
222        }  
223        
224        sb.AppendLine("\tSyntaxHighlighter.all();");
225        sb.AppendLine("</script>");
226        page.ClientScript.RegisterStartupScript(page.GetType(), "SyntaxHighlighter", sb.ToString(), false);
227    }
228
229    private static string GetUrl(string folder, string url)
230    {
231        string s = HttpContext.Current.Server.UrlPathEncode(string.Format("{0}{1}", folder, url));
232        if (!folder.ToLowerInvariant().Contains("http:") && !folder.ToLowerInvariant().Contains("https://"))
233            s = Utils.ApplicationRelativeWebRoot + s;
234        return s;
235    }
236    
237    #endregion
238
239    #region Private methods
240
241    private static void InitSettings()
242    {
243        // call Options getter so default settings are loaded on application start.
244        var s = Options;
245    }
246
247    static string OptionsHelp()
248    {
249        StringBuilder sb = new StringBuilder();
250        sb.AppendLine("<p>This extension implements excellent Alex Gorbatchev's syntax highlighter JS library for source code formatting. Please refer to <a target=\"_new\" href=\"http://alexgorbatchev.com/wiki/SyntaxHighlighter:Usage\">this site</a> for usage.</p>");
251        sb.AppendLine("<p><b>cdnScriptsPath</b>: Allows you to load the SyntaxHighlighter script from a CDN. Leave empty for local files</p>");
252        sb.AppendLine("<p><b>cdnStylesPath</b>: Allows you to load the SyntaxHighlighter styles from a CDN. Leave empty for local files</p>");
253        sb.AppendLine("<p><b>auto-links</b>: Allows you to turn detection of links in the highlighted element on and off. If the option is turned off, URLs won't be clickable.</p>");
254        sb.AppendLine("<p><b>collapse</b>: Allows you to force highlighted elements on the page to be collapsed by default.</p>");
255        sb.AppendLine("<p><b>gutter</b>:	Allows you to turn gutter with line numbers on and off.</p>");
256        sb.AppendLine("<p><b>smart-tabs</b>:	Allows you to turn smart tabs feature on and off.</p>");
257        sb.AppendLine("<p><b>tab-size</b>: Allows you to adjust tab size.</p>");
258        sb.AppendLine("<p><b>toolbar</b>: Toggles toolbar on/off.</p>");
259        sb.AppendLine("<p><a target=\"_new\" href=\"http://alexgorbatchev.com/wiki/SyntaxHighlighter:Configuration\">more...</a></p>");
260        return sb.ToString();
261    }
262
263    static string GetOption(string opt)
264    {
265        if (Options != null)
266        {
267            string pattern = "\tSyntaxHighlighter.defaults['{0}'] = {1};";
268            string val = Options.GetSingleValue(opt).ToLowerInvariant();
269            return string.Format(pattern, opt, val);
270        }
271        return "";
272    }
273
274    static string ScriptsFolder()
275    {
276        if (Options != null)
277        {
278            if (!String.IsNullOrEmpty(Options.GetSingleValue("cdnScriptsPath")))
279                return Options.GetSingleValue("cdnScriptsPath");
280            else
281                return "Scripts/syntaxhighlighter/";
282        }
283        return "";
284    }
285
286    static string StylesFolder()
287    {
288        if (Options != null)
289        {
290            if (!String.IsNullOrEmpty(Options.GetSingleValue("cdnStylesPath")))
291                return Options.GetSingleValue("cdnStylesPath");
292            else
293                return "Styles/syntaxhighlighter/";
294        }
295        return "";
296    }
297
298    #endregion
299}