Well, it is time for part 2. In this part I will detail rendering the syntax highlighting to an Image, showing that image just in the Editor view.
Generating the HTML
In order to generate an image of the code highlighting, I needed to actually generate an HTML page and make the call to the JavaScript library. By looking at the samples on SyntaxHighlighter’s Installation Page, it is pretty easy to construct a template html page to be embedded in your plugin library as a resource. I wrote a helper class in charge of consuming the resource, linking the JavaScript, linking the CSS, and finally substituting our plugin’s html.
Generating the Image
Generating an image of the rendered HTML is pretty straight forward, thanks to the HtmlScreenCapture class. The constructor takes the html as an argument, and the CaptureHtml method takes a timeout as an argument.
Linking the Image
One of the hardest parts of this phase was determining how to display a dynamic local image in the Editor window. For this, I turned to WindowsLiveLocal.WriterPlugin.dll, specifically the MapContenSource. First, we need to be able to save the generated image somewhere temporary, and then we need to recall it, telling WLW to render it. I knew there was a built in plugin for Bing’s Map API, and it makes sense that this type of plugin would need to answer the same questions.
Due to the lack of resources I found, reverse engineering became crucial for the success of this plugin. Back in the MapContentSource (using Reflector or your favorite .Net Decompiler), I came across the solution to the first part: UpdateMapImage.
internal static void UpdateMapImage(ISmartContent content, MapSettings settings, Size newSize)
{
...
HtmlScreenCapture capture = new HtmlScreenCapture(...);
Bitmap image = capture.CaptureHtml(0xafc8);
if (image != null)
{
...
content.Files.AddImage(settings.ImageFileId, image, ImageFormat.Jpeg);
}
}
Notice after generating the Map image, MapContentSource adds the image to a “Files” collection with some sort of unique ID. Displaying this map is found in the GenerateHTML Method:
private string GenerateHtml(ISmartContent content, bool editor, string blogId)
{
...
Uri uri = content.Files.GetUri(settings.ImageFileId);
if (uri != null)
{
caption = string.Format(CultureInfo.InvariantCulture,..., new object[] { HtmlServices.HtmlEncode(uri.ToString()), str3, HtmlServices.HtmlEncode(plainText) });
}
}
As show above, the solution is simply to reference the image again using that same unique ID. The result is a uri that can be used directly as the “src” attribute of the image.
Wrapping this Up
Using the findings from above, here is the compiled code my plugin uses to generate an image on the fly that is given just to the editor, and not the publisher (remember the two methods from part 1?).
public override string GenerateEditorHtml(ISmartContent content, IPublishingContext publishingContext)
{
string html = PreviewHtmlCreator.Create(publishingContext, _language, _code);
HtmlScreenCapture capture = new HtmlScreenCapture(html, Width) { MaximumHeight = (int)(_lineCount * 16) };//16 lineheight in IE
Bitmap image = capture.CaptureHtml(1000);
content.Files.AddImage(ImageFieldId, image, ImageFormat.Bmp);
Uri uri = content.Files.GetUri(ImageFieldId);
return String.Format(...image tag..., HtmlServices.HtmlEncode(uri.ToString()), _size.Width, _size.Height);
}
And for comparison:
public override string GeneratePublishHtml(ISmartContent content, IPublishingContext publishingContext)
{
return String.Format(ContentFormat, _language.ToLower(), _code);
}
In Summary
We have explored the Windows Live Writer API, and found a way to create a plugin that allows for dynamic image content while maintaining separate html for preview and editor files. Check out the plugin page for more information.