using System; using System.Text.RegularExpressions; using BlogEngine.Core; using BlogEngine.Core.Web.Controls; [Extension("Adds a link to syntax highlighted code to copy it to the clipboard.", "1.0", @"Troy Goode")] public class CopyCodeToClipboard { private ExtensionSettings settings; public CopyCodeToClipboard() { Post.Serving += new EventHandler(Post_PostServing); Post.Saving += new EventHandler(Post_Saving); ExtensionSettings initialSettings = new ExtensionSettings(GetType().Name); initialSettings.Help = "This extension is written to work with the Code Snippet Plugin for Windows Live Writer and will not work with other syntax highlighting tools."; initialSettings.AddParameter( "copyText", "Text for 'Copy to Clipboard' button?", 255, true ); initialSettings.AddValue( "copyText", "Copy To Clipboard" ); initialSettings.AddParameter( "popupText", "Text for 'View in Popup Window' button?", 255, true ); initialSettings.AddValue( "popupText", "View Plain" ); initialSettings.AddParameter("aboveBelow", "Display above or below code?", 5, true); initialSettings.AddValue("aboveBelow", "Below"); initialSettings.AddParameter( "style", "Any additional styling?", int.MaxValue, false ); initialSettings.AddValue( "style", "" ); initialSettings.AddParameter( "flashFile", "Path to '_clipboard.swf' Flash file?", 255, true ); initialSettings.AddValue( "flashFile", "~/_clipboard.swf" ); initialSettings.IsScalar = true; ExtensionManager.ImportSettings(initialSettings); settings = ExtensionManager.GetSettings(GetType().Name); } private void Post_Saving(object sender, SavedEventArgs e) { //### executing here will only run the code once per post, but will modify the post itself //InsertCopyCodeLink(e); } private void Post_PostServing(object sender, ServingEventArgs e) { //### executing here will execute the code on every iteration, but will not modify your post InsertCopyCodeLink(e); } private void InsertCopyCodeLink( ServingEventArgs e) { if( !string.IsNullOrEmpty(e.Body) ) { //### find code-div string postID = Guid.NewGuid().ToString().Replace( "{", "" ).Replace( "}", "" ).Replace( "-", "" ); string toFind = "
"; int index = e.Body.IndexOf(toFind); while( index != -1 ) { //### grab code out of code-div int end = e.Body.IndexOf( "
", index ); //### the first should be the end of "csharpcode" end = e.Body.IndexOf( "", end ); //### the next should be the end of "csharpcode-wrapper" string code = e.Body.Substring(index, end - index); //### parse code out of code-div int codeStart = code.IndexOf("
") + 6;
				code = code.Substring(codeStart, codeEnd - codeStart);
				code = Regex.Replace( code, @"<(.|\n)*?>", string.Empty ); //### strip html
				code = code.Replace( " ", "" ); //### remove unnecessary  s from the blank lines
				code = code.Replace( " ", " " ); //### convert  s to spaces
				code = Regex.Replace( code, @"^(\s*)(\d+): ", "" ); //### remove line numbers on first line
				code = Regex.Replace( code, @"(\n)(\s*)(\d+): ", "\n" );  //### remove line numbers on subsequent lines

				//### create copy link
				string insertScript = @"
					";
				string insertDiv = @"
@POPUPTEXT | @COPYTEXT
"; //### set values for copy link and insert above/below code string insert = insertDiv + OutputCommonMethods() + insertScript; insert = insert.Replace( "@STYLE", settings.GetSingleValue("style") ); insert = insert.Replace( "@POPUPTEXT", settings.GetSingleValue("popupText") ); insert = insert.Replace( "@COPYTEXT", settings.GetSingleValue("copyText") ); insert = insert.Replace( "@INDEX", postID + "_" + index.ToString() ); //### use index of code-div as a unique ID to allow multiple code-divs on this post insert = insert.Replace( "@CODE", code.Replace( "\\", "\\\\" ).Replace( "'", "\\'" ).Replace( "\r\n", "\\r\\n" ).Replace( "\\r\\n\\r\\n\\r\\n", "\\r\\n" ) ); if( settings.GetSingleValue("aboveBelow").ToLower() == "above" ) e.Body = e.Body.Insert( index, insert ); else e.Body = e.Body.Insert( e.Body.IndexOf( "", end + 1 ) + 6, insert ); //### prep index to find next code-div index = index + insert.Length + 1; //### ensure we don't find this same code-div again if( index > e.Body.Length ) break; index = e.Body.IndexOf( toFind, index ); //### find any other code divs } } } private string OutputCommonMethods() { //### only output the following once per page if( System.Web.HttpContext.Current.Items["CopyToClipboard_JSOutput"] == null ) { //### add shared javascript string flashPath = System.Web.VirtualPathUtility.ToAbsolute(settings.GetSingleValue("flashFile")); string commonMethods = @"
"; System.Web.HttpContext.Current.Items["CopyToClipboard_JSOutput"] = true; return commonMethods; } else return ""; } }