PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

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

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