<rss version="2.0">
  <channel>
    <title>Markdown Monster Blog</title>
    <link>https://markdownmonster.west-wind.com/blog/</link>
    <image>
      <url>ImageUrl</url>
      <title>Markdown Monster Blog</title>
      <link>https://markdownmonster.west-wind.com/blog/</link>
    </image>
    <description>Wind, waves, code and everything in between</description>
    <copyright>(c) West Wind Technologies 2006-2026</copyright>
    <pubDate>2026-09-08T14:20:49.0898258Z</pubDate>
    <lastBuildDate>2026-09-08T05:20:36.5572313Z</lastBuildDate>
    <generator>Rick Strahl's West Wind Weblog</generator>
    <item>
      <title>Markdown Monster 4.5 Release Notes</title>
      <description><![CDATA[<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/ReleaseBanner.jpg" alt="Release Banner"></p>
<p>Markdown Monster 4.5 - although a point release - is a major update to Markdown Monster. This releases replaces the main editor rendering surface with Microsoft's <a href="https://microsoft.github.io/monaco-editor/">Monaco Editor</a> from the original <a href="https://ace.c9.io/">ACE Editor</a> implementation.</p>
<p>ACE has been a wonderful platform to work with over the years and it has powered MM's editing experience for years. But Monaco brings a number of useful built-in editor features that previously required custom implementations or simply weren't practical to integrate.</p>
<p>Monaco is the editor core behind VS Code, but Markdown Monster's implementation sticks to the core editor engine features without many of the distracting pop up features and completions. For the most part the move to the new editor surface is not drastically different than the old ACE based interface and it most definitely doesn't make Markdown Monster just another VS Code variation.</p>
<p>What changes are some of the editor chrome features, like the scrollbars, minimap, find and replace and diff viewer that are native in Monaco. Additionally Monaco provides a more complete API to access internal features of the editor which allow more control over implementing custom features in the editor along with better documentation and better support for agents to help in improving Markdown Monster's feature set.</p>
<h2 id="whats-new-in-45">What's New in 4.5</h2>
<p>So let's dive in and take a look what's new and improved.</p>
<h3 id="inline-diff-editing-see-what-changed-right-where-youre-working">Inline Diff Editing: See What Changed, Right Where You're Working</h3>
<p>One of the primary reasons for the switch to Monaco was support for inline Diff editing. Diff editing is becoming increasingly more important in this age of agents where we often need to see changes to documents to compare old and changed text.</p>
<p>Markdown Monster internally uses several different operations for diff viewing:</p>
<ul>
<li>Startup Recovery Files (ie. hard exits or shutdowns before files were saved)</li>
<li>Showing live diffs between the editor document and what was on disk when opened</li>
<li>Showing Git Commit differences</li>
</ul>
<p>Recovery File Detection is based on Backup files that show changes that were not saved for some reason. This could be a system or app crash, or any reason that caused the application to not finish a normal shutdown.</p>
<p>When you start back up you'd see something like this now in v4.5:</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/Diff-Backup-File.png" alt="Diff Backup File"><br>
<small><strong>Figure 1</strong> - Showing an inline Diff for non-saved changes from a previous run. You can edit the document in the Diff view. </small></p>
<p>You can jump out of Diff Mode into the regular editor view via the Tab or the Editor Context menu:</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/OutofDiffMode.png" alt="Out of Diff Mode"><br>
<small><strong>Figure 2</strong> - Jumping out of Diff mode via Close Diff View returns you back into the standard editor without Diff</small></p>
<p>When you <strong>Close Diff View</strong> the Diff is effectively aborted. If you want to accept changes you have to individually accept the changes or all changes using the various hover options on the diff items.</p>
<p>To show changes of the current document vs. what's stored on disk you can use the <strong>Open in Diff Editor</strong> Tab or Editor Context menu option:</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/OpenInDiffEditor.png" alt="Open In Diff Editor"><br>
<small><strong>Figure 3</strong> - Open in Diff Editor shows file differences between the edited file and what's on disk</small></p>
<p>Finally you can also open the Diff Editor on any file from the Folder Browser if it is managed by Git. When you open the file as Diff Editor from the Folder Browser the file then shows the uncommitted differences of the file.</p>
<p>These operations in the past brought an optionally configured external diff editor to view the differences, but this integrated view</p>
<h3 id="find-and-replace-that-doesnt-get-in-your-way">Find and Replace That Doesn't Get in Your Way</h3>
<p>The old ACE Editor find and replace dialog has always been clunky as it used very old school design that didn't fit into a desktop style UI. In the old version we ended up using custom CSS to restyle the Find and Replace popup, but due to the way ACE has this designed not everything was easy to style. In addition there were keyboard navigation with the original implementation that would in some scenarios transfer key operations pointing at the find dialog getting pushed into the editor.</p>
<p>With the adoption of Monaco we've inherited a much cleaner Find and Replace dialog that works correctly out of the box with navigation keystrokes. Monaco's finder also automatically highlights matches in the document (as did ACE) <strong>and</strong> also on the scrollbar so you can see at a glance where in the document matches live.</p>
<p>The familiar shortcuts still apply: <strong>Ctrl+F</strong> opens Find and <strong>Ctrl+H</strong> opens Replace.</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/Find-and-Replace.png" alt="Monaco Find and Replace in Markdown Monster, searching for Monaco and preparing to replace it with Monaco Editor.">
<small><strong>Figure 4</strong> - Monaco provides improved Find and Replace dialog behavior</small></p>
<h3 id="an-optional-minimap-for-longer-documents">An Optional Minimap for Longer Documents</h3>
<p>Another nice improvement based on Monaco is the availability of an optional MiniMap of the document near the left scrollbar. Minimap provides a very dense layout of the document in the scrollbar area that lets you roughly see what the document looks like. It's useful in some situations to quickly jump to the appropriate document sections.</p>
<p>Personally I'm not a fan, but I know a lot of people who use this feature to navigate their documents and now that ability is hear courtesy of the Monaco editor integration.</p>
<p>If you like that visual overview, enable <strong>ShowMiniMap</strong> in the Options dialog. You can also enable it through the <code>Editor.showMiniMap</code> setting.</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/Minimap-and-Scroll-Markers.png" alt="Markdown Monster's minimap beside a longer document, with spelling underlines and corresponding yellow markers near the scrollbar.">
<small><strong>Figure 5</strong> - Minimap gives you a compressed visual view of your document for navigation purposes</small></p>
<p>The Minimap is optional, and <strong>it's off by default</strong>, so you have to explicitly enable it in the settings.</p>
<h3 id="scrollbar-markers-a-quick-view-of-things-to-review">Scrollbar Markers: A Quick View of Things to Review</h3>
<p>Another benefit of Monaco is that information from inside the document can also appear as markers along the scrollbar.</p>
<p>The scrollbar highlights:</p>
<ul>
<li>Spelling Errors</li>
<li>Current Selection Matches</li>
<li>In Diff Mode, document changes</li>
</ul>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/ScrollbarMarkers.png" alt="Scrollbar Markers"><br>
<small><strong>Figure 6</strong> - Scrollbar markers show selection matches, spelling errors and document changes when in Diff mode</small></p>
<p>This feature is a subtle one, but it's useful when reviewing a long post. You can quickly get a feel where relevant text or spell errors live.</p>
<h3 id="razor-and-curl-syntax-highlighting">Razor and cURL Syntax Highlighting</h3>
<p>This release also adds support for ASP.NET Razor and cURL syntax highlighting both inline in the editor <strong>and</strong> in the rendered preview output. Use <code>razor</code> or <code>curl</code> after the opening code fence to identify the language:</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/Razor-and-Curl-Editor-and-Preview.png" alt="Razor and cURL fenced code samples, with Markdown source on the left and syntax-highlighted preview on the right."><br>
<small><strong>Figure 7</strong> - Razor and cUrl syntax coloring both in the editor and previewer</small></p>
<blockquote>
<p><i class="fas fa-warning" style="font-size: 1.1em"></i>  Make sure your Hosting Platform Supports these formats
Markdown Monster's preview uses <a href="https://highlightjs.org/">highlightJs</a> to produce highlighted syntax blocks, along with a custom extension to provide a toolbox with the syntax type and copy option.</p>
<p>One caveat is worth keeping in mind when publishing: <strong>The Markdown file doesn't carry its syntax highlighter with it.</strong> The language name on a code fence tells the receiving renderer what the block contains, but the website still needs a highlighter that supports that language. If your hosting platform doesn't support the syntax you may see generic code rendering.</p>
<p>You can incorporate MM's syntax coloring extensions in your own custom HTML. <a href="https://markdownmonster.west-wind.com/docs/Recipes/Source-Code-Syntax-Highlighting-in-exported-HTML.html">More info here...</a></p>
</blockquote>
<h3 id="updated-highlightjs-in-the-preview">Updated Highlight.js in the Preview</h3>
<p>Speaking of <strong>highlighJs</strong> Markdown Monster now uses the latest version of this great JavaScript library. Due to some legacy code in the previous versions of Markdown Monster, we were using a quite old versions of highlightJs until this release. The new version adds a few additional syntaxes (see previous) and the highlighter runs more efficiently on the page for rendering, especially in very large documents.</p>
<h3 id="window-resizing-now-preserves-editorpreview-size-ratio">Window Resizing now preserves Editor/Preview Size Ratio</h3>
<p>This update also changes the Window resizing behavior for editor and preview panes. Previously the Preview pane was fixed in size and any Window resizing would only resize the Editor pane. In the new release the editor preview size ratio is preserved when the Window is resized so both editor and preview adjust size to stay in roughly the same layout ratio.</p>
<h3 id="external-programs-more-useful-paths-less-placeholder-guesswork">External Programs: More Useful Paths, Less Placeholder Guesswork</h3>
<p>External Programs let you add your own <strong>Open...</strong> commands for tools outside Markdown Monster. They're handy for opening a file in another editor or launching a terminal where you're working.</p>
<p>Previously, these definitions used numeric placeholders such as <code>{0}</code> and <code>{1}</code>. Those continue to work, but looking at a command months later and remembering which number means which value isn't especially intuitive.</p>
<p>You can now use descriptive names instead:</p>
<table>
<thead>
<tr>
<th>Placeholder</th>
<th>Expands to</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>{CurrentFile}</code></td>
<td>The selected file's path</td>
</tr>
<tr>
<td><code>{CurrentFolder}</code></td>
<td>The current file's containing folder</td>
</tr>
<tr>
<td><code>{CurrentRow}</code></td>
<td>The current editor row</td>
</tr>
<tr>
<td><code>{CurrentColumn}</code></td>
<td>The current editor column</td>
</tr>
<tr>
<td><code>{ProjectFolder}</code></td>
<td>The project base folder, or the current folder when no project base is found</td>
</tr>
</tbody>
</table>
<p><small><em>(<a href="https://markdownmonster.west-wind.com/docs/Configuration-Settings/Run-External-Programs-via-Open-With.html#configuring-external-programs">full docs here</a>)</em></small></p>
<p>For an editor that accepts a file, row, and column, an argument string is much easier to understand when written as:</p>
<pre><code class="language-json">&quot;ExternalPrograms&quot;: [
{
    &quot;Name&quot;: &quot;Open in VS Code&quot;,
    &quot;Executable&quot;: &quot;C:\\Program Files\\Microsoft VS Code\\Code.exe&quot;,
    &quot;Args&quot;: &quot;\&quot;{CurrentFile}:{CurrentRow}:{CurrentColumn}\&quot; -g \&quot;{ProjectFolder}\&quot;&quot;,
    &quot;SaveBeforeActivation&quot;: false,
    &quot;Extensions&quot;: &quot;TEXT,FOLDER&quot;,
    &quot;EditorKeyboardShortcut&quot;: null
}
</code></pre>
<p>The named placeholders also make it easier to distinguish the current document's folder from the project root. If you're editing <code>docs\guides\publishing.md</code>, you may want a terminal at the project root, not inside <code>docs\guides</code>.</p>
<p>For example, an External Program definition that launches Windows Terminal (<code>wt.exe</code>) can use its starting-directory argument:</p>
<pre><code class="language-text">-d &quot;{ProjectFolder}&quot;
</code></pre>
<p>MM expands the project path, and Windows Terminal uses that path as its working directory. Other tools can use the same placeholder with their own directory options.</p>
<p>The project folder comes from MM's <a href="https://markdownmonster.west-wind.com/docs/Recipes/Configuring-Site-Relative-Base-Paths.html#site-relative-path-overrides">project base-path and marker-file configuration</a>, so it can point above the current document's folder. Quote path placeholders, as in these examples, to handle folders and filenames that contain spaces.</p>
<p>You can reach the definitions through <strong>Open... &gt; Edit External Programs...</strong> on the document tab's context menu. Existing numeric placeholders are still recognized, so the named versions improve readability without requiring you to rewrite every working command.</p>
<h2 id="wrapping-up">Wrapping Up</h2>
<p>Although on the surface this release is only a point release, behind the scenes this release is a major update due to the complexities of replacing the internal editor engine from ACE editor to Microsoft's Monaco editor. The reason for this major change is that Monaco is better supported than ACE and includes a number of useful features that are useful to Markdown Monster that were not easily achievable using ACE editor. Many of these features come courtesy of the editor in the box, without any special customizations.</p>
<p>The inline diff editor is the biggest visible addition for reviewing changes. The improved search UI, minimap, and scrollbar markers are smaller conveniences that help while you're actually working in a document. Add the syntax and external-tool improvements, and there's quite a bit here beyond a different editing engine.</p>
<p>You can find builds on the <a href="https://markdownmonster.west-wind.com/download">Markdown Monster download page</a> and the full release history in the <a href="https://github.com/RickStrahl/MarkdownMonster/blob/main/Changelog.md">changelog</a>.</p>
<div style="margin-top: 30px;font-size: 0.8em;
            border-top: 1px solid #eee;padding-top: 8px;">
    <img src="https://markdownmonster.west-wind.com/favicon.png" style="height: 20px;float: left; margin-right: 10px;">
    this post was created and published with the 
    <a href="https://markdownmonster.west-wind.com" target="top">Markdown Monster Editor</a> 
</div>
]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2026/Sep/07/Markdown-Monster-45-Release-Notes</link>
      <guid isPermaLink="false">mc0m7f3o8fji</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2026/Sep/07/Markdown-Monster-45-Release-Notes#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2026/Sep/07/Markdown-Monster-45-Release-Notes</guid>
      <pubDate>Mon, 07 Sep 2026 19:20:36 GMT</pubDate>
      <abstract><![CDATA[Markdown Monster 4.5 replaces the legacy ACE editing surface with Microsoft's Monaco Editor. This update brings integrated inline diff editing, an improved Find and Replace experience, an optional document minimap, and helpful scrollbar markers. Version 4.5 also adds Razor and cURL syntax highlighting, an upgraded Highlight.js engine, proportional editor resizing, and cleaner named placeholders for launching external tools.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2026/Markdown-Monster-4-5-Release-Notes/ReleaseBanner.jpg</featuredImage>
    </item>
    <item>
      <title>Windows Protected your PC: Dealing with Windows SmartScreen  on Installation</title>
      <description><![CDATA[<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Windows-Protected-your-PC-Dealing-with-Windows-SmartScreen-on-Installation/SmartScreenBanner.jpg" alt="Smart Screen Banner">
Windows SmartScreen also known as the  <strong>Windows protected your PC</strong> screen, is a scourge on users and small software publishers as it is a reputation based mechanism that Windows uses to scare people from installing external software.</p>
<p>And yeah, while it's fine to notify users that software loaded from an Internet download can potentially cause harm, it's a pain to users unfamiliar with how SmartScreen works or how you can bypass it to install software, despite the scary warning because they trust the source.</p>
<p>That said - always do your <strong>Due Diligence</strong> and make sure you trust the vendor and the Web site. If not sure, do your research, check reviews and make sure the software is downloaded from the vendor directly or from a reputable alternate source like a package manager, or a trusted download site.</p>
<p><a href="https://markdownmonster.west-wind.com?ut=weblog"  target="_blank"
	  title="Markdown Monster - Easy to use, yet powerfully productive Markdown Editing for Windows">
<img src="https://markdownmonster.west-wind.com/blog/images/sponsors/banner-example.png?v=1.2" class="da-content-image" />
</a></p>
<p>If you've run into the lovely Blue <strong>Windows protected your PC</strong> screen when installing software from a Web download:</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Windows-Protected-your-PC-Dealing-with-Windows-SmartScreen-on-Installation/WindowsSmartBlueScreen.png" alt="Windows Smart Blue Screen"><br>
<small><strong>Figure 1</strong> - A scary SmartScreen dialog when you try to install an application</small></p>
<p>you know what I mean.</p>
<p>As publisher of small software packages like <a href="https://markdownmonster.west-wind.com">Markdown Monster</a>,  <a href="https://documentationmonster.com">Documentation Monster</a> and <a href="https://websurge.west-wind.com">West Wind WebSurge</a> I run into this issue <strong>every single time I upload a new release</strong> for public downloads. These are small vendor software applications and because SmartScreen keys of downloaded files and successful installations, they are very negatively affected by 'scary' SmartScreen popups, scaring off customers when initial versions are posted or updated. If users get scared off they're unlikely to return.</p>
<p>Eventually as reputation of the downloads improves due to successful installations, SmartScreen backs off, but the cycle repeats next time a new version is uploaded. In a couple of words: It sucks!</p>
<h2 id="working-around-the-problem">Working around the Problem</h2>
<p>Before I go into why SmartScreen pushes those prompts on users, let me give you the quick fix for SmartScreen in most scenarios, assuming you want to install the software regardless of the warning.</p>
<p>You can do the following:</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2026/Windows-Protected-your-PC-Dealing-with-Windows-SmartScreen-on-Installation/ByPassingSmartScreen.png" alt="Bypassing Windows SmartScreen"><br>
<small><strong>Figure 2</strong> - You can bypass SmartScreen by clicking the not so obvious <strong>More info</strong> link.</small></p>
<p>SmartScreen in most scenarios gives you the option of bypassing the warning and installing anyway:</p>
<ul>
<li>Click on the <strong>More info</strong> Link</li>
<li>Check and make sure the Installer Signature matches the vendor</li>
<li>If you're sure you trust the vendor and signature</li>
<li>Click on the <strong>Run anyway</strong> button</li>
</ul>
<p>SmartScreen is meant to prevent you from doing a drive-by install of software by bringing up the blue warning screen, letting you know that you are installing <strong>potentially</strong> unsafe software.</p>
<p><strong>Fair enough</strong> - if you install software directly from the Internet, it's possible to install unsafe software that can do bad things to your computer and installed software.</p>
<p>I don't have an issue with popping up the warning screen, because that's a legitimate concern. The way it's done - well, that's a different story - as that form is one big scare tactic from the blue screen to the lack of information about <strong>why</strong> you might be careful, and how you should proceed. Instead this window works through obfuscation by seemingly just giving one choice: <strong>Don't run</strong>.</p>
<p>As you've seen you can bypass, but you should most definitely be careful and check the source.</p>
<blockquote>
<h5 id="--make-sure-you-trust-the-vendor"><i class="fas fa-warning" style="font-size: 1.1em"></i>  Make sure you Trust the Vendor!</h5>
<p>You want to make absolutely sure you trust the vendor and the site of the software that you're trying to install. Bad things can happen if you install Malware, and there's no vetting process for any software directly downloaded from the Web.</p>
<p>If you use the bypass described above, make sure you are familiar with the vendor or the product and check that the signature of the package matches the vendors contact information.</p>
<p>It's good practice when installing software from an unknown vendor, to check reviews or online discussions around the product to ensure the software is legit and comes from a vendor approved download location! There's a surprising amount of information available to let you know if specific software is problematic. Better safe than sorry!</p>
</blockquote>
<h3 id="better-vetting-and-local-installs-for-software-use-a-package-manager">Better Vetting and Local Installs for Software: Use a Package Manager</h3>
<p>One way to have a more secure experience is to install software from the Windows Store (if available) or from a Package Manager like WinGet or <a href="https://community.chocolatey.org/">Chocolatey</a>. These stores and package manager platforms review software before it's published, run malware checks and run through automated tests that check for successful installations and side effects on the system. This process isn't fool proof - but it's often a lot better than installing a random product from a random Web site.</p>
<blockquote>
<h5 id="--unigetui---a-manager-for-windows-store-and-package-managers"><i class="fas fa-lightbulb" style="font-size: 1.1em"></i>  UniGetUi - A Manager for Windows Store and Package Managers</h5>
<p>If you want to install from any of these sources check out <a href="https://devolutions.net/unigetui/">UniGetUi</a>, which is a free desktop application that lets you search for, install and update software from a number of different stores and package managers. It's a great one-stop tool that lets you hit all sources in one place.</p>
</blockquote>
<p>Package managers have an additional advantage over straight downloaded software in that they typically avoid SmartScreen due to Mark of the Web. Because these managers internally download software rather than pulling it down through a browser, installers are run as local executables that don't have a Mark of the Web that triggers SmartScreen (among other things).</p>
<p>Essentially this means, package managers typically bypasses most of the SmartScreen security flags.</p>
<p>Here are a couple of examples of package managers you can run from the Windows Terminal:</p>
<pre><code class="language-ps">winget install MarkdownMonster
choco install DocumentationMonster
</code></pre>
<p>... or you can use UniGetUi if you prefer a GUI application.</p>
<p>All of these package managers and the store include commands to update and list already installed components, which is an additional benefit.</p>
<p>Package Managers provide some basic curation for published packages, doing virus scanning  and associating publishers with products consistently and removing packages and publishers that are problematic quickly. Before packages are published there's some pre-validation happening by the provider that provides to at least a base level of security compared to what you get directly downloading software.</p>
<p>For this to work, software publishers of Software have to ensure that their software is published on these package managers and kept up to date. Unlike Windows Store however, the process of publishing to package managers - while not exactly simple - is usually well defined and can be completely automated making it something that is a viable alternative for downloads for publishers. You often find way more software on the package managers than you will find in the Windows Store because of it's restrictive requirements.</p>
<p>In short, if you're not sure about some software you're trying to download, downloading froma package manager is often the best approach.</p>
<p>All of the West Wind product download pages have links for Chocolatey and WinGet installers as alternatives to the direct download. Even so, I'm always surprised that the vast majority of users are installing directly from the download - I guess there's some trust there which is good 😄</p>
<p>If you are a vendor linking the various package managers supported on the download page is a good idea, so users that run into problems with your direct download can try the alternate potentially less intrusive package installs.</p>
<h3 id="remove-mark-of-the-web">Remove Mark-Of-The-Web</h3>
<p>Another option is to download installers and explicitly remove the Mark-of-the-Web attached to downloaded binaries and installers.</p>
<p>SmartScreen is triggered among other things by Mark-of-the-Web which indicates that a file was downloaded from the Web. Any file downloaded through a browser interface gets marked and Windows detects this mark changing the security consideration of the file.</p>
<p>The various package managers avoid Mark-of-the-Web by directly downloading package content and locally unpacking thereby bypassing the Mark-of-the-Web and thus usually get around SmartScreen.</p>
<p>You can also remove this mark yourself on any downloaded file that gives you security issues when downloaded off the Web.</p>
<blockquote>
<p>Unblock-File -Path '.\MarkdownMonsterSetup.exe'</p>
</blockquote>
<p>This removes the Mark-Of-The-Web and likely will not trigger SmartScreen on install, even if the required reputation level has not been achieved.</p>
<p>Mark of the Web is not the only criterion but it's a big contributor for SmartScreen popups especially with new downloads.</p>
<h3 id="windows-store">Windows Store</h3>
<p>Microsoft suggests publishing apps through the Windows Store. Windows Store is a curated platform, and software has to go through a very thorough vetting process. The problem is that this process is both slow and cumbersome and there are a million different rules that have to be followed including some restrictions the software can and can't do in some cases requiring that Windows Store versions have to be dumbed down to be eligible for Store publishing.</p>
<p>Developer and developer adjacent tools in particular have a hard time conforming to all the rules, and the lack of attention by reviewers to real-world concerns in the app publishing process make the Windows Store a time consuming pain in the ass.</p>
<p>I had gone through this process on multiple occasions only to be rejected due to a various shell features that are perfectly adequate for the application and just were rejected outright. Bottom line is that not every product can go into the Windows Store.</p>
<p>I don't have the time or resources to deal with Windows Store deployment, plus for commercial software the model going to the store adds additional complexity and fees again resulting in changes to the application to make the Store work.</p>
<p>In the case of West Wind products the effort is not worth the reward.</p>
<h2 id="smartscreen-rant">SmartScreen Rant</h2>
<p>As you can tell I'm not a big fan of SmartScreen. Few people - even users - are. I'm not against warning users of the dangers of installing software from the Web or networks in general. But heavy handely and effectively scaring users into avoiding installing software that they might even trust, is something else. And that's really what SmartScreen does.</p>
<p>The issue I have with SmartScreen and its UI are many:</p>
<ul>
<li>It doesn't tell you anything other than <em>&quot;Big Scary Warning, Don't Do it!&quot;</em></li>
<li>The Bypass operation is obscured and totally un-obvious</li>
<li>Conversely at first glance the only option appears to be <strong>Don't run</strong></li>
<li>There's no continuity for the vendor publishing updates -<br>
the more frequently you publish, the more painful SmartScreen is</li>
</ul>
<h2 id="how-does-smartscreen-work">How does SmartScreen Work</h2>
<p>The actual semantics behind how SmartScreen are not officially disclosed by Microsoft, but based on observation I can make some guesses. At the end of the day SmartScreen is a reputation based system.</p>
<p>When updating Markdown Monster to a new Version and immediately downloading and installing it after the new version is live - I always get a SmartScreen dialog when running the installer. After a few hours - and presumably some users that fought their way past SmartScreen, SmartScreen stops showing up. However, your mileage may vary based on your machine or company security policy.</p>
<p>Things that affect SmartScreen popups:</p>
<ul>
<li><p><strong>Unsigned Binaries and Installers</strong><br>
Unsigned installer always trigger Windows SmartScreen. If the publisher has not signed their binary that's usually not a good sign, but it's not uncommon for open source tools, and small utilities. Be extra careful with these types of installations and make sure triple sure you trust the publisher. Do your research!</p>
</li>
<li><p><strong>No or few successful Installations</strong><br>
SmartScreen is reputation based and as such even a signed binary, that has just been uploaded for download is likely to trigger SmartScreen. As more people download and successfully install the software, SmartScreen stops being so aggressive and allows installation. It appears SmartScreen uses Windows statistics for installations, crashes and uninstalls to determine whether an app is 'stable' and doesn't cause problems.</p>
</li>
</ul>
<p>The problem with the latter Installation counting is that every time an update is shipped, the reputation cycle starts over. There's no continuity over the name of the binary or the certificate used - nothing. Even a vendor like me shipping typically weekly updates of the same software with the same cert for 10 years - same shit each and every time.</p>
<p>For Markdown Monster this is not a huge problem, because the reputation turnaround comes quickly enough due to a fair number of downloads. It also helps that it's geared to a tech savvy audience that presumably knows how to bypass SmartScreen.</p>
<p>However, for a new product like Documentation Monster that is relatively unknown and gets only a few downloads, it may never clear the SmartScreen Reputation hurdle between updates because the download count is low. In the meantime SmartScreen's scary warning ensure that many users may never actually install.</p>
<p>New software with a scary blue screen pop up, is simply not a great recipe for getting new users to try out the software for the first time.</p>
<p><a href="https://amzn.to/3EaiBqi"  target="_blank"
		  title="Broken Money - A Comprehensive Overview of the Past, Present, and Future of Money">
<img src="https://markdownmonster.west-wind.com/blog/images/sponsors/BrokenMoney-Display.jpg" class="da-content-image" />
</a></p>
<h2 id="summary">Summary</h2>
<p>At the end of the day SmartScreen is just something developers and end users have to put up with. It's frustrating that Microsoft has taken such an aggressive approach with SmartScreen rather than providing a more productive approach of providing a Warning Screen with more information and a clearer way to allow for bypassing the warnings when you are sure you want to install anyway.</p>
<p>But alas here we are...</p>
<div style="margin-top: 30px;font-size: 0.8em;
            border-top: 1px solid #eee;padding-top: 8px;">
    <img src="https://markdownmonster.west-wind.com/favicon.png" style="height: 20px;float: left; margin-right: 10px;">
    this post created and published with the 
    <a href="https://markdownmonster.west-wind.com" target="top">Markdown Monster Editor</a> 
</div>
]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2026/Jun/01/Windows-Protected-your-PC-Dealing-with-Windows-SmartScreen-on-Installation</link>
      <guid isPermaLink="false">1xpe0ed8a2gs</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2026/Jun/01/Windows-Protected-your-PC-Dealing-with-Windows-SmartScreen-on-Installation#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2026/Jun/01/Windows-Protected-your-PC-Dealing-with-Windows-SmartScreen-on-Installation</guid>
      <pubDate>Mon, 01 Jun 2026 11:54:24 GMT</pubDate>
      <abstract><![CDATA[Windows SmartScreen’s "Windows protected your PC" warning often scares users away from legitimate software. This post explores why this reputation-based mechanism triggers—even for signed binaries from established developers—and provides a step-by-step guide for users to bypass the obscured "More info" dialog. It also discusses alternative installation methods, such as WinGet and Chocolatey, to avoid these warnings and improve the user experience for small software vendors.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2026/Windows-Protected-your-PC-Dealing-with-Windows-SmartScreen-on-Installation/SmartScreenBanner.jpg</featuredImage>
    </item>
    <item>
      <title>Create a .NET PlantUML Markdown Render Extension</title>
      <description><![CDATA[<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2024/Create-a-PlantUML-RenderExtension-in-Markdown-Monster/PlantUMLBanner.jpg" alt="Plant Uml Banner"></p>
<p>It's been a while since I've posted some Markdown Monster content, so I thought I'd share a fun feature I recently added to my <a href="https://markdownmonster.west-wind.com/">Markdown Monster editor</a>. In the process I'll highlight a useful library and service that is <a href="https://www.plantuml.com/">PlantUML</a>, and how you can add  support for it in your own C# code, or use a custom <strong>RenderExtension</strong> in Markdown Monster or elsewhere to pre-process Markdown for PlantUML diagrams. Although this code discusses a Markdown Monster and custom blog implementation, the code I show is mostly generic and can be used easily with your own .NET code.</p>
<p>I arrived here, because a number of people requested preview rendering support for PlantUML in Markdown Monster. I previously hadn't heard much about PlantUML and so my initial reaction was not to since it's kind of niche. But I got several other requests in short order and so I took a look at how PlantUML integration would work. Turns out it's fairly easy to integrate with minimal external dependencies (unlike Mermaid or nomnoml) as it generates fully self-contained image output.</p>
<p><a href="https://markdownmonster.west-wind.com?ut=weblog"  target="_blank"
	  title="Markdown Monster - Easy to use, yet powerfully productive Markdown Editing for Windows">
<img src="https://markdownmonster.west-wind.com/blog/images/sponsors/banner-example.png?v=1.2" class="da-content-image" />
</a></p>
<h2 id="what-is-plantuml">What is PlantUML</h2>
<p><a href="https://www.PlantUML.com/">PlantUML</a> is a diagramming tool, and as the name suggests primarily produces <a href="https://plantuml.com/">UML related diagrams</a> but there are a number of other useful diagrams types you can create as well, including visualizations for JSON, YAML, and RegEx and Deployment, Network, Gannt and MindMap charts. Similar to tools like Mermaid or nomnoml, but more focused and with an easier server based usage model, it allows for embedding of diagrams as <code>png</code> or <code>svg</code> images into your text.</p>
<p>The tool is server based, and it works by sending a markup expression that in return generates image content that can be embedded into an <code>&lt;img src&gt;</code> tag. There are no further dependencies or other libraries - just ready to use images that are embedded into HTML.</p>
<p>All the work with PlantUML happens on the server that converts encoded PlantUML markup into an image. There's a public PlantUML server you can use,  or you can also run PlantUML on your own either as a Java Server application or via Docker image. Regardless of mode you're interacting with a very simple HTTP GET API that expects an encoded version of PlantUML markup.</p>
<p>Here's what some of the PlantUML diagrams look like:</p>
<blockquote>
<p><small><em>Note: markup sample text blocks have an extra space inserted before the <code> ```plantuml</code> code directive for rendering purposes in the post. Remove the the space in your actual Markdown markup.</em></small></p>
</blockquote>
<h3 id="use-case">Use Case</h3>
<p><a href="http://www.plantuml.com/plantuml/uml/JCWn3a104030Vb-n9OK2lVY3UC25nSNjhUpj5Twcy2HVK4bqatckkq_cr387IBkFXrF7o19bsbIOq3GJ15eCJL3zkXdENcaoBn76H5fZLNLO32PwrYLy-6tpRVFVjeIUufmvl0000F__0m00" target="_blank"><img src="http://www.plantuml.com/plantuml/png/JCWn3a104030Vb-n9OK2lVY3UC25nSNjhUpj5Twcy2HVK4bqatckkq_cr387IBkFXrF7o19bsbIOq3GJ15eCJL3zkXdENcaoBn76H5fZLNLO32PwrYLy-6tpRVFVjeIUufmvl0000F__0m00" alt="diagram"></a></p>
<pre><code class="language-markdown"> ```plantuml
@startuml
skinparam monochrome true
left to right direction
User1 --&gt; (Story1)
(Story1) --&gt; (Story2)
(Story2) --&gt; (Story3)
@enduml
```
</code></pre>
<hr>
<h3 id="sequence-diagram">Sequence Diagram</h3>
<p><a href="http://www.plantuml.com/plantuml/uml/J8yz3i8m34Ptdy8NOA3bHs90_CyWSG4tpL0fn90w0sTZu4XS0JMco9cUlYT7Uf_NUzCB9Sct07TAqhdkJb7mR9XwF343EU64-hQ6LK-XuHnRIizXsnbMNu7ZA8b3kTaRLb-3Zz99kK0y6bO_WvQ46khzi1qCK_5pS1o2Tz9nx75lMFq27jddSe285yFgbt1YnicwjE0AhumQRFPAzp7Kc5hDBz68cGfjC_jSzx79cCNurR_0o6LnfGGsFhRv5hu0003__mC0" target="_blank"><img src="http://www.plantuml.com/plantuml/png/J8yz3i8m34Ptdy8NOA3bHs90_CyWSG4tpL0fn90w0sTZu4XS0JMco9cUlYT7Uf_NUzCB9Sct07TAqhdkJb7mR9XwF343EU64-hQ6LK-XuHnRIizXsnbMNu7ZA8b3kTaRLb-3Zz99kK0y6bO_WvQ46khzi1qCK_5pS1o2Tz9nx75lMFq27jddSe285yFgbt1YnicwjE0AhumQRFPAzp7Kc5hDBz68cGfjC_jSzx79cCNurR_0o6LnfGGsFhRv5hu0003__mC0" alt="diagram"></a></p>
<pre><code class="language-markdown"> ```plantuml
@startuml
participant Participant as Foo
actor       Actor       as Foo1
boundary    Boundary    as Foo2
control     Control     as Foo3
entity      Entity      as Foo4
database    Database    as Foo5
collections Collections as Foo6
queue       Queue       as Foo7
Foo -&gt; Foo1 : To actor 
Foo -&gt; Foo2 : To boundary
Foo -&gt; Foo3 : To control
Foo -&gt; Foo4 : To entity
Foo -&gt; Foo5 : To database
Foo -&gt; Foo6 : To collections
Foo -&gt; Foo7: To queue
@enduml```
</code></pre>
<hr>
<p><a href="http://www.plantuml.com/plantuml/uml/NCv12i8m58JX_Jl5q9MzHK7Sk5Oeb1JIva62CId9AxI89tFXaRo2H574xSSFCu_RlScYasJjXIu4xESicBns0SAB4D0ThCjm6USLmomIWo9WKmF7C5eUJsoGj76nQ5jZ-sUT-Ys7k1HhrRTxIxKBmkcr2Sk90LG4z9zn3PFYv5sMdgxKS33byXC00F__0m00" target="_blank"><img src="http://www.plantuml.com/plantuml/png/NCv12i8m58JX_Jl5q9MzHK7Sk5Oeb1JIva62CId9AxI89tFXaRo2H574xSSFCu_RlScYasJjXIu4xESicBns0SAB4D0ThCjm6USLmomIWo9WKmF7C5eUJsoGj76nQ5jZ-sUT-Ys7k1HhrRTxIxKBmkcr2Sk90LG4z9zn3PFYv5sMdgxKS33byXC00F__0m00" alt="diagram"></a></p>
<pre><code class="language-markdown"> ```plantuml
@startsalt
{
  Just plain text
  [This is my button]
  ()  Unchecked radio
  (X) Checked radio
  []  Unchecked box
  [X] Checked box
  &quot;Enter text here   &quot;
  ^This is a droplist^
}
@endsalt
```
</code></pre>
<hr>
<h3 id="classes">Classes</h3>
<p><a href="http://www.plantuml.com/plantuml/uml/V8wn2i8m48RtFiLF9aKSN4C8L5q4STBTK689j1LorwdqoHny95z1aeRQAhZaoDrttt-lnxEe315sBV6zjXvT1W0hd4nj8K7iNLD2gTAorb2AGarCNWR4DVmpxxEa3My-IeVleYNhIHwEZbXTo7gzd2zinuMEsB0hUkpjpRGL1neIiQJCH8OMGM9Y_I86zRzm4RlNZL1dZIxhitJ-UgqX9XU8c3QRnlZ19pwUDm000F__0m00" target="_blank"><img src="http://www.plantuml.com/plantuml/png/V8wn2i8m48RtFiLF9aKSN4C8L5q4STBTK689j1LorwdqoHny95z1aeRQAhZaoDrttt-lnxEe315sBV6zjXvT1W0hd4nj8K7iNLD2gTAorb2AGarCNWR4DVmpxxEa3My-IeVleYNhIHwEZbXTo7gzd2zinuMEsB0hUkpjpRGL1neIiQJCH8OMGM9Y_I86zRzm4RlNZL1dZIxhitJ-UgqX9XU8c3QRnlZ19pwUDm000F__0m00" alt="diagram"></a></p>
<pre><code class="language-markdown"> ```plantuml
class Customer {
    + Name : string &lt;&lt;get&gt;&gt; &lt;&lt;set&gt;&gt;
    + Age : int &lt;&lt;get&gt;&gt; &lt;&lt;set&gt;&gt;
}
class ClassA {
    + ClassA(users:IList&lt;User&gt;)
}
class ClassB {
    + {static} DefaultUser : User &lt;&lt;get&gt;&gt;
    + Users : IList&lt;User&gt; &lt;&lt;get&gt;&gt;
    + ClassB(users:IList&lt;User&gt;)
}
class &quot;IList`1&quot;&lt;T&gt; {
}
ClassA --&gt; &quot;DefaultUser&quot; User
ClassA --&gt; &quot;Users&lt;User&gt;&quot; &quot;IList&lt;User&gt;&quot;
```
</code></pre>
<hr>
<h3 id="json">Json</h3>
<p><a href="http://www.plantuml.com/plantuml/uml/R96nJiCm441tVyNfPYebRb9GfrPi35awLOZ1n0unE7Raku0gr2zZu9Fu1MGdXQNZFVkUd-IVh-yTiOhyIi6BJm60dOt4ZHeCRW4VGk_n9c6d_kbXiDpFsDBUsVT4EKuc8_MIHdat3rf7GuHRI78098x6yFuFeon1UWs7pBCK05lBftJOc0yuXlXsuSIASq9plA0n42jt7tJcPL78ShKkYm85m3atZ7tmffc6PnFJYuzvRyu1G3wDURCFWrcS0EZpzRbFGbtNgrAkg-HSh5SCeUjiUzMngJRPKTMRsyKX09voNTjRfwFngMmcD8Q9aj5Fpecps1clq__y0W00__y30000" target="_blank"><img src="http://www.plantuml.com/plantuml/png/R96nJiCm441tVyNfPYebRb9GfrPi35awLOZ1n0unE7Raku0gr2zZu9Fu1MGdXQNZFVkUd-IVh-yTiOhyIi6BJm60dOt4ZHeCRW4VGk_n9c6d_kbXiDpFsDBUsVT4EKuc8_MIHdat3rf7GuHRI78098x6yFuFeon1UWs7pBCK05lBftJOc0yuXlXsuSIASq9plA0n42jt7tJcPL78ShKkYm85m3atZ7tmffc6PnFJYuzvRyu1G3wDURCFWrcS0EZpzRbFGbtNgrAkg-HSh5SCeUjiUzMngJRPKTMRsyKX09voNTjRfwFngMmcD8Q9aj5Fpecps1clq__y0W00__y30000" alt="diagram"></a></p>
<pre><code class="language-markdown"> ```plantuml
@startjson
{
  &quot;firstName&quot;: &quot;John&quot;,
  &quot;lastName&quot;: &quot;Smith&quot;,
  &quot;isAlive&quot;: true,
  &quot;age&quot;: 28,
  &quot;address&quot;: {
    &quot;streetAddress&quot;: &quot;21 2nd Street&quot;,
    &quot;city&quot;: &quot;New York&quot;,
    &quot;state&quot;: &quot;NY&quot;,
    &quot;postalCode&quot;: &quot;10021-3100&quot;
  },
  &quot;phoneNumbers&quot;: [
    {
      &quot;type&quot;: &quot;home&quot;,
      &quot;number&quot;: &quot;212 555-1234&quot;
    },
    {
      &quot;type&quot;: &quot;office&quot;,
      &quot;number&quot;: &quot;646 555-4567&quot;
    }
  ],
  &quot;children&quot;: [],
  &quot;spouse&quot;: null
}
@endjson
```
</code></pre>
<p>The output generated can be in various formats:</p>
<ul>
<li>png - Image</li>
<li>svg - drawing</li>
<li>txt - ASCII Art (yes!)</li>
<li>uml - links to the interactive editor on the PlantUML site</li>
</ul>
<p>Here's what a full Url looks like:</p>
<pre><code class="language-text">http://www.plantuml.com/plantuml/png/&lt;encodedPlantUmlMarkup&gt;
</code></pre>
<h2 id="markdown-and-custom-extensions">Markdown and Custom Extensions</h2>
<p>My use case is specifically for using PlantUML inside of Markdown text and for live preview and output generation in Markdown Monster and in various Markdown rendering Web applications. As I show at the end of this post - I also need it to render this output on my blog, which currently uses a custom Markdown rendering scheme that doesn't have support for PlantUML, and I'll discuss how to add it there using a similar mechanism to what I'll use for Markdown Monster and which is more generic and something you can plug into your own applications.</p>
<h3 id="markdown">Markdown</h3>
<p>Markdown is a basic markup language that takes text based markup and turns it into HTML. It has a decent set of markup features tailored to representing common HTML constructs typically used for document based HTML layout. Markdown's most common uses are for articles, blog posts, documentation etc. - basically anything that creates document centric output. Markdown is not a good fit for fancy HTML layout as it lacks native constructs for styling or even CSS classes. Markdown is all about text and content, that can be flowed into existing document templates.</p>
<p>Markdown works great for text scenarios, but even there... the set of features is fixed and somewhat limited. There are a number of non-standard Markdown extension formats that are widely recognized and have in a way created a new standard, like GitHub Flavored Markdown (GFM), custom code blocks with syntax highlighting, annotations, generic attributes, media embedding etc. which all are not part of the base Markdown 'standard', but are widely supported by most platforms.</p>
<h3 id="markdown-customization">Markdown Customization</h3>
<p>Customization beyond that however is often <strong>specific to the platform or tooling</strong>. So Mermaid charts and PlantUML diagrams tend to be selectively supported by various platforms so you have to think about where your Markdown will end up. For example, GitHub now supports Mermaid as of late 2022, but it doesn't support PlantUML. GitLab supports both. BitBucket supports Mermaid, but not PlantUML and so on. So even if a tool like Markdown Monster adds support for PlantUML in its previewer and output generation, if it doesn't work on GitHub where your Markdown eventually ends up, it's not terribly useful. If I want to publish to GitLab or my blog which now supports PlantUML, it's very useful.</p>
<blockquote>
<p><strong>In short: Know your Target Markdown Platform</strong> and ensure it supports the features you are using before committing to adding features that might not work where you deploy your final Markdown to.</p>
</blockquote>
<h2 id="creating-plantuml-output">Creating PlantUML output</h2>
<p>The image Url is a sent to a live PlantUML service that creates images on the fly via HTTP GET requests that contain the PlantUML markup in an encoded and compressed format. The online server is surprisingly fast - fast enough in fact to use it in live previews in Markdown Monster where you can type in the PlantUML code, and immediately see changed output reflected (within Markdown Monster's typing delay) in the HTML preview.</p>
<p>In Markdown Monster, I capture the PlantUML markup with the common Markdown code syntax using <code> ```plantuml</code> as shown above, and then using a <code>MarkdownRenderExtension</code> that transforms any of these <code> ```plantuml</code> code blocks into an image HTML element that replaces the code block at render time.</p>
<p>The embedded PlantUML image that replaces the <code> ```plantuml</code> code block looks like this:</p>
<pre><code class="language-html">&lt;img src=&quot;http://www.PlantUML.com/PlantUML/png/UhzxVt9EOd6nWdDfSKb-...003__mC0&quot;
     alt=&quot;diagram&quot;&gt;
</code></pre>
<p>The Url in this case points to the PlantUML server that's online, and processes requests very quickly but there are some usage limits in place. If you plan to do high volume of requests you might want to run a local server instead so you don't get blocked for excessive volume. The PlantUML server rate blocking limits are more than reasonable for casual use, but if you're using server generated code in a Web application for many users, you might need to look at hosting your own PlantUML server.</p>
<p>PlantUML is an open source Java server application, so you can run the server natively or using a provided Docker image in a container on your own hosted server.</p>
<ul>
<li><a href="https://PlantUML.com/starting">Getting Started with the PlantUML server</a></li>
</ul>
<h3 id="oddball-encoding">Oddball Encoding</h3>
<p>PlantUML works via plain HTTP GET Urls that return a binary PNG or SVG result. The only tricky part about this process is an unconventional Url encoding scheme plus deflate compression to produce the encoding token that is sent in the Url.</p>
<p>I found an existing C# version by <a href="https://github.com/incongruousm">Jason Deabill (GitHub)</a> of this encoder that is covered in this <a href="https://gist.github.com/incongruousm/509ef8820532883f9899b6e980ef6503">blog post</a> and available as a gist:</p>
<script src="https://gist.github.com/incongruousm/509ef8820532883f9899b6e980ef6503.js"></script>
<p>The code produces just the encoded token, and you then append the base Url to use for an <code>&lt;img&gt;</code> tag which again looks like this:</p>
<pre><code class="language-html">&lt;img src=&quot;http://www.PlantUML.com/PlantUML/png/UhzxVt9EOd6nWdDfSKb-...003__mC0&quot;
     alt=&quot;diagram&quot;&gt;
</code></pre>
<h2 id="markdown-monster-and-plantuml">Markdown Monster and PlantUML</h2>
<p>Over the last year or so several people have requested support for PlantUML and since it's pretty straight forward to get live rendering of a diagram using the PlantUML server, this is a nice feature that could be added to Markdown Monster with minimal effort.</p>
<p>There are other Markdown tools that also have support for PlantUML (including a VS Code addin), and Markdown Monster uses the same syntax using a custom 'code block' syntax that looks like this:</p>
<p>As mentioned the syntax for this looks like this, embedded into Markdown text:</p>
<pre><code class="language-markdown"> ```plantuml
@startuml
skinparam monochrome true
left to right direction
User1 --&gt; (Story1)
(Story1) --&gt; (Story2)
(Story2) --&gt; (Story3)
@enduml
```
</code></pre>
<p>In order to get this to work in Markdown Monster, it needs to:</p>
<ul>
<li>Check for the <code> ```plantuml</code> code block</li>
<li>Extract the PlantUML code block</li>
<li>Encode the PlantUML code for the Url</li>
<li>Create a fully qualified PlantUML Url</li>
<li>Replace the code block with the image</li>
</ul>
<p>Since this isn't a native Markdown feature, nor an add-in supported by the <a href="https://github.com/xoofx/markdig">MarkDig Markdown Parser</a> that Markdown Monster uses, the easiest way to provide this functionality is to create a <strong>MarkdownRenderExtension</strong>.</p>
<h3 id="markdown-monster-markdownrenderextensions">Markdown Monster MarkdownRenderExtensions</h3>
<p>Markdown Monster has support for an <code>IMarkdownRenderExtension</code> interface that allows for the original Markdown or rendered HTML to be modified as it passes through the Markdown processing pipeline. You can pre-process the markdown before it is rendered, and post process the HTML after it's been rendered essentially replacing the input and output string, before the final rendered HTML is provided to the Previewer or for output generation to HTML or PDF. A Render Extension is implemented as a class that implements <code>IMarkdownRenderExtension</code> and that is then added to a RenderExtensions collection that is processed on every Markdown parsing request.</p>
<p>In the case of the PlantUML Render Extension the extension parses the inbound Markdown text, and replaces any <code> ```plantuml</code> code blocks with the PlantUML <code>&lt;img&gt;</code> HTML element.</p>
<h3 id="creating-a-renderextension">Creating a RenderExtension</h3>
<p>MarkdownRenderExtensions generally are pretty simple text parsing affairs - they are meant to look either at the original Markdown pre-rendering or the rendered HTML post rendering, and extract some text and replace it with something else. It's a powerful, but simple tool to extend Markdown rendering process for custom formatting or content transformation, and the PlantUML extension is a perfect example of that as it transforms a PlantUML codeblock into an image.</p>
<p>Markdown Monster ships with several internal render extensions for expanding FontAwesome icons, embedding Mermaid charts, embedding automatic Table of Contents and now for PlantUML diagram transformations. End users of the application can also create their own RenderExtensions by creating a Markdown Monster Addin and adding their own <code>IMarkdownRenderExtension</code> to <code>MarkdownRenderExtensionsManager.Current.RenderExtensions.Add(extension)</code>.</p>
<blockquote>
<p>It's important to understand that MarkdownRenderExtensions are Markdown Monster specific, so any feature implemented as a MarkdownRenderExtension is not guaranteed to work anywhere else but for MM's output rendering.</p>
<p>However, in the case of the PlantUML Render Extension, MM uses standard PlantUML Markdown syntax that is supported by various Git hosting platforms and tools, so while the render extension is not used by those platforms you get the same render output for PlantUML (as long as the Git hosting/rendering platform supports it). Notably GitHub <strong>does not</strong> support PlantUML directly, but GitLab does. Other tools that support PlantUML include VS Code and Notepad++ (via addins).</p>
</blockquote>
<p>Since this addin ends up being a built-in Render Extension in Markdown Monster, I don't need to create a seperate addin (it's good to be king!), but I'll discuss briefly how to create a MM addin at the end. At this point I'll focus on the Render Extension code itself that showcases how to create the image URL and extract the markup.</p>
<p>The PlantUML <code>MarkdownRenderExtension</code> specifically uses a RegEx expression to find the <code> ```plantuml</code> code blocks and replaces them with <code>&lt;img&gt;</code> elements wrapped into a link that jumps to the PlantUML server to allow interactively editing the markup.</p>
<p>Here's the code:</p>
<pre><code class="language-csharp">public class PlantUmlRenderExtension : IMarkdownRenderExtension
{
    private const string StartUmlString = &quot;\n```plantuml&quot;;       
    private static readonly Regex plantUmlRegex = new Regex(@&quot;(\n```plantuml[\S\s]).*?([\s\S]```)&quot;, RegexOptions.Singleline);
  
    public void BeforeMarkdownRendered(ModifyMarkdownArguments args)
    {
        if (string.IsNullOrEmpty(args.Markdown) ||
            !args.Markdown.Contains(StartUmlString))
            return;

        var markdown = args.Markdown;
        var matches = plantUmlRegex.Matches(markdown);
        foreach(var match in matches)
        {
            var origBlock = match?.ToString();
            var umlBlock = origBlock.TrimStart();
            if (umlBlock.StartsWith(&quot;```&quot;))                
                umlBlock = umlBlock.Replace(&quot;```plantuml&quot;,string.Empty).Trim(' ', '`', '\n', '\r');

            var url = mmApp.Configuration.Markdown.PlantUmlServerUrl + PlantUmlTextEncoding.EncodeUrl(umlBlock);                                
            var html = $&quot;&lt;img src=\&quot;{url}\&quot; alt=\&quot;diagram\&quot; /&gt;&quot;;

            if (url.Contains(&quot;plantuml.com&quot;))
            {
                var linkUrl = url.ReplaceMany([&quot;/svg/&quot;, &quot;/png/&quot;, &quot;/txt/&quot;], &quot;/uml/&quot;);
                if (!string.IsNullOrEmpty(linkUrl))
                    html = $&quot;&lt;a href=\&quot;{linkUrl}\&quot; target=\&quot;_blank\&quot;&gt;{html}&lt;/a&gt;&quot;;
            }

            markdown = markdown.Replace(origBlock, html);
        }
     
        args.Markdown = markdown;
    }

    public void AfterMarkdownRendered(ModifyHtmlAndHeadersArguments args)
    { }

    public void AfterDocumentRendered(ModifyHtmlArguments args)
    { }        
}
</code></pre>
<p><small><strong>Listing 1</strong> - extract PlantUML code blocks and replace with rendered diagram images </small></p>
<p>This <code>MarkdownRenderExtension</code> implements on the <code>BeforeMarkdownRendered()</code> which receives the original Markdown text as input. The code walks through the Markdown and replaces the <code> ```plantuml</code> code blocks with a raw HTML <code>&lt;img&gt;</code> link. The image then gets rendered instead of the code block in the final output to produce the desired inline diagram.</p>
<p><a href="https://goldenbeartshirts.com"  target="_blank"
	  title="Bears and Beer">
<img src="https://markdownmonster.west-wind.com/blog/images/Sponsors/BearsBeer-Display.jpg" class="da-content-image" />
</a></p>
<h3 id="creating-a-markdown-monster-addin-for-a-markdownrenderextension">Creating a Markdown Monster Addin for a MarkdownRenderExtension</h3>
<p>Markdown Monster can be extended via Addins and if you want to create your own custom MarkdownRenderExtension in order to preview some custom markup, you can do so via a Markdown Monster addin.</p>
<ul>
<li><a href="https://markdownmonster.west-wind.com/docs/_4ne0s0qoi.htm">Creating a Markdown Monster Addin</a></li>
<li><a href="https://markdownmonster.west-wind.com/docs/_5i30sba89.htm">Creating a Markdown Monster Markdown Render Extension</a></li>
</ul>
<p>In summary creating an addin for .NET 8.0 involves:</p>
<pre><code class="language-ps">dotnet new install MarkdownMonster.AddinProject.Template

# Create a folder for your project and change to it
md \projects\SampleAddin
cd \projects\SampleAddin

# Create the new Project - make sure the name ends in 'Addin'
dotnet new markdownmonsteraddin -n SampleAddin --company &quot;West Wind Technologies&quot;

# Build the project - should create a placeholder addin
dotnet build 
</code></pre>
<p>Once you've created the addin you can create a new RenderExtension class in the project:</p>
<pre><code class="language-cs">public class SampleRenderExtension : IMarkdownRenderExtension
{
    // Inject markdown text into the bottom of the document
    public void BeforeMarkdownRendered(ModifyMarkdownArguments args)
    {
        // add some text at the end of the markdown
        args.Markdown += $&quot;\n\n&lt;small&gt;generated by Sample Addin {DateTime.Now.ToString(&quot;d&quot;)}&lt;/small&gt;\n\n&quot;;
    }

    // Add Headers for the `&lt;head&gt;` section of the template
    // and optionally modify the rendered Markdown HTML
    public void AfterMarkdownRendered(ModifyHtmlAndHeadersArguments args)
    {
    }

    // update the final HTML that involves HTML that is part of the template
    public void AfterDocumentRendered(ModifyHtmlArguments args)
    {
    }
}
</code></pre>
<p><small><strong>Listing 2</strong> - Creating a customer Render Extension in Markdown Monster</small></p>
<p>To hook up this <code>SampleRenderExtension</code>, add it to the RenderExtensions collection in the Addin's <code>OnApplicationStart()</code> method:</p>
<pre><code class="language-cs">public override async Task OnApplicationStart()
{
    // ... other generated stuff 
    
    MarkdownRenderExtensionsManager.Current.RenderExtensions.Add(new SampleRenderExtension());
}
</code></pre>
<p><small><strong>Listing 3</strong> - Adding a RenderExtension in a Markdown Monster Addin</small></p>
<p>And that's all there's to it...</p>
<p>When the project builds, it's automatically built into the Addins folder so it should be locally usable, and you can <a href="https://github.com/RickStrahl/MarkdownMonsterAddinsRegistry">optionally publish the addin to the Addin repository</a>.</p>
<p><a href="https://websurge.west-wind.com?ut=weblog"  target="_blank"
	  title="West Wind WebSurge - A powerful, yet easy to use REST Client and HTTP Load Testing tool for Windows">
<img src="https://markdownmonster.west-wind.com/blog/images/Sponsors/Websurge-Display.png" class="da-content-image" />
</a></p>
<h2 id="final-thoughts-implementing-markdownrenderextensions-in-markdown-for-your-own-applications">Final Thoughts: Implementing MarkdownRenderExtensions in Markdown for your own Applications</h2>
<p>RenderExtension processing like this is easy to implement and it has many uses, but this is a <strong>Markdown Monster specific feature</strong>. Previewer and output generation works in MM, but - as I just realized, it didn't work on my Blog, which uses custom Markdown rendering and which <strong>does not have support for PlantUML</strong>. Ooops! 😂</p>
<p>This is the point I highlighted earlier:</p>
<blockquote>
<p>Know where your Markdown ends up before committing to using a non-standard feature like PlantUML.</p>
</blockquote>
<p>Since my blog is a custom implementation and uses custom Markdown rendering (using a the same engine as MM does, but without the MM specific extension model) I ended up implementing <code>IMarkdownRenderExtension</code> into my custom Markdown renderer. As it turns out that's relatively simple if you have a single point parsing implementation as I do (which incidentally is nearly the same as what I use in Markdown Monster and in <code>Westwind.AspNetCore.Markdown</code>).</p>
<p>I've added it now, and the reason you can see the expanded PlantUML diagrams from the top of the post rendered into the page is because of the new RenderExtension.</p>
<p>In case you want to do something similar in your own apps, here's the implementation and integration of <code>IMarkdownRenderExtension</code>:</p>
<pre><code class="language-csharp">public interface IMarkdownRenderExtension
{
    void BeforeMarkdownRendered(ModifyMarkdownArguments args);

    void AfterMarkdownRendered(ModifyHtmlAndHeadersArguments args);

    void AfterDocumentRendered(ModifyHtmlArguments args);

}
// modify original Markdown text
public class ModifyMarkdownArguments
{
    public ModifyMarkdownArguments(string markdown = null, MarkdownDocument doc = null)
    {
        Markdown = markdown;
        MarkdownDocument = doc;
    }

    public string Markdown { get; set; }

    public MarkdownDocument MarkdownDocument { get; }
}

// modify rendered Html text
public class ModifyHtmlAndHeadersArguments
{
    public ModifyHtmlAndHeadersArguments(string html = null, string markdown = null, MarkdownDocument doc = null)
    {
        Html = html;
        Markdown = markdown;
        MarkdownDocument = doc;
    }

    public string Html { get; set; }

    public string Markdown { get; }

    public string HeadersToEmbed { get; set; }

    public MarkdownDocument MarkdownDocument { get; }
}

//  modify final rendered HTML (in template situations)
public class ModifyHtmlArguments
{
    public ModifyHtmlArguments(string html = null, string markdown = null, MarkdownDocument doc = null)
    {
        Html = html;
        Markdown = markdown;
        MarkdownDocument = doc;
    }

    public string Html { get; set; }

    public string Markdown { get; }

    public MarkdownDocument MarkdownDocument { get; }
}
</code></pre>
<p><small><strong>Figure 2</strong> - Implement your own RenderExtensions with pre and post Markdown render processing</small></p>
<p>The arguments essentially pass in the <code>Markdown</code> or <code>Html</code> properties as string properties that can be modified and are then passed through the render pipeline.</p>
<p>I like to create an application wide <code>MarkdownRenderExtensionsManager</code> with a static <code>Current</code> property so i can globally access and add/remove/manage the applied Render Extensions for the application.</p>
<pre><code class="language-csharp">public class MarkdownRenderExtensionsManager
{
    
    /// &lt;summary&gt;
    /// Global application instance of the Extensions Manager
    /// &lt;/summary&gt;
    public static MarkdownRenderExtensionsManager Current { get; }

    /// &lt;summary&gt;
    /// Active Render Extensions. You can add your own extensions on application startup
    /// &lt;/summary&gt;
    public List&lt;IMarkdownRenderExtension&gt; RenderExtensions { get; set; } = new();

    static MarkdownRenderExtensionsManager()
    {
        Current = new MarkdownRenderExtensionsManager();
        
        // apply default extensions
        Current.RenderExtensions.Add( new PlantUmlRenderExtension() );
        Current.RenderExtensions.Add( new FontAwesomeIconsRenderExtension() );
    }
    
}    
</code></pre>
<p><small><strong>Listing 3</strong> - using a Singleton class via the <code>Current</code> prop to manage application wide Render Extension usage</small></p>
<p>Next you need to hook the actual pre and post processing into your Markdown parsing pipeline. In my apps I use a Markdown Parser wrapper with a <code>Parse()</code> method where I can apply the <code>MarkdownRenderExtension</code> processing:</p>
<pre><code class="language-csharp">public class MarkdownParserMarkdig : IMarkdownParser
{
    public static MarkdownPipeline Pipeline;

    public List&lt;IRenderExtension&gt; RenderExtensions { get; set;  } 

    public MarkdownParserMarkDig() 
    {
            if (Pipeline == null)
            {
                Pipeline = new MarkdownPipelineBuilder()
                //.UsePipeTables()
                //.UseAutoLinks()
                //.UseCitations()
                //.UseEmphasisExtras()
                //.UseDiagrams()
                .UseEmojiAndSmiley()                
                .UseAdvancedExtensions()
                .UseYamlFrontMatter()
                .Build();
            }

            RenderExtensions = new List&lt;IRenderExtension&gt;();
            RenderExtensions.Add(new PlantUmlRenderExtension());
    }
    
    public string Parse(string markdown)
    {
        if (string.IsNullOrEmpty(markdown))
            return string.Empty;
    
        // Markdown RenderExtension Handling
        foreach(var renderExtension in MarkdownRenderExtensionsManager.Current.RenderExtensions)
        {
            var args = new ModifyMarkdownArguments(markdown);
            renderExtension.BeforeMarkdownRendered(args);
            markdown = args.Markdown;
        }
    
        var html = Markdown.ToHtml(markdown, Pipeline);
        html = HtmlUtils.SanitizeHtml(html);
        html = ParseFontAwesomeIcons(html);
    
        // Rendered Html RenderExtension Handling
        foreach (var renderExtension in MarkdownRenderExtensionsManager.Current.RenderExtensions)
        {
            var args = new ModifyHtmlAndHeadersArguments(html, markdown);
            renderExtension.AfterMarkdownRendered(args);
            html = args.Html;
        }
    
        return html;
    }
</code></pre>
<p><small><strong>Listing 4</strong> - Hooking up custom Render Extension processing. Just add additional extensions as needed.</small></p>
<p>My Markdown parser simply has a <code>Parse()</code> method which in this case calls into <code>Markdig.ToHtml()</code> to render the Markdown to HTML. The class wrapper is used to support multiple classes and also to configure MarkDig and which features of its pipeline you want to use when parsing.</p>
<p>With all of this in place I can now apply any Render Extension like the PlantUML version shown in <strong>Listing 1</strong>.</p>
<p>A bonus feature in the future might be to build a PlantUML <strong>MarkDig extension</strong>. When I have some time I might look into that, but it's a bit more work than the simple <code>PlantUmlRenderExtension</code> mechanism shown here. Oh and I think I need to add MarkdownRenderExtension support to my existing Markdown libraries. But I leave that for another day 😄</p>
<h2 id="resources">Resources</h2>
<ul>
<li><a href="https://PlantUML.com/starting">Getting Started with the PlantUML server</a></li>
<li><a href="">Westwind.AspNetCore.Markdown</a></li>
</ul>
<div style="margin-top: 30px;font-size: 0.8em;
            border-top: 1px solid #eee;padding-top: 8px;">
    <img src="https://markdownmonster.west-wind.com/favicon.png" style="height: 20px;float: left; margin-right: 10px;">
    this post created and published with the 
    <a href="https://markdownmonster.west-wind.com" target="top">Markdown Monster Editor</a> 
</div>
]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2024/Jul/29/Create-a-Dotnet-PlantUML-Markdown-Render-Extension</link>
      <guid isPermaLink="false">j28zz98icr72</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2024/Jul/29/Create-a-Dotnet-PlantUML-Markdown-Render-Extension#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2024/Jul/29/Create-a-Dotnet-PlantUML-Markdown-Render-Extension</guid>
      <pubDate>Mon, 29 Jul 2024 09:16:35 GMT</pubDate>
      <abstract><![CDATA[PlantUML is a Web based diagramming markup language that can be used to create diagrams using text descriptions that are rendered into images via a PlantUML server. In this post I describe how you can integrate PlantUML image rendering into your .NET application, specifically from a Markdown rendering perspective as Markdown documents are the most common mechanism that PlantUML output is delivered.]]></abstract>
      <featuredImage>https://weblog.west-wind.com/images/2024/Create-a-PlantUML-RenderExtension-in-Markdown-Monster/PlantUMLBanner.png</featuredImage>
    </item>
    <item>
      <title>Taking down the Markdown Monster Source Code</title>
      <description><![CDATA[With a heavy heart and a lot of hand wringing, I decided last week to take down the Markdown Monster source code from the public GitHub repository due to rampant abuse of the code to get around licensing restrictions. In this post I give some insight on why I made this decision and provide some general thoughts around the state of software development for software tools.]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2021/May/05/Taking-down-the-Markdown-Monster-Source-Code</link>
      <guid isPermaLink="false">0zdrjmu7db6y</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2021/May/05/Taking-down-the-Markdown-Monster-Source-Code#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2021/May/05/Taking-down-the-Markdown-Monster-Source-Code</guid>
      <pubDate>Wed, 05 May 2021 12:51:41 GMT</pubDate>
      <abstract><![CDATA[With a heavy heart and a lot of hand wringing, I decided last week to take down the Markdown Monster source code from the public GitHub repository due to rampant abuse of the code to get around licensing restrictions. In this post I give some insight on why I made this decision and provide some general thoughts around the state of software development for software tools.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2021/Taking-down-the-Markdown-Monster-Source-Code/Denied.png</featuredImage>
    </item>
    <item>
      <title>Why use a dedicated Markdown Editor?</title>
      <description><![CDATA[Most generic editors have support for Markdown syntax and for many basic markdown editing tasks that might be fine. But if you're extensively working with Markdown on a regular basis it is constructive to use a dedicated Markdown editor that understands many common Markdown operations and can greatly simplify and speed them up as well as providing useful support features for linking and embedding. In this post I describe why I use a dedicated Markdown editor rather than a generic editor for my Markdown editing.]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2019/May/25/Why-use-a-dedicated-Markdown-Editor</link>
      <guid isPermaLink="false">isc3be1m50tz</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2019/May/25/Why-use-a-dedicated-Markdown-Editor#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2019/May/25/Why-use-a-dedicated-Markdown-Editor</guid>
      <pubDate>Sat, 25 May 2019 22:46:24 GMT</pubDate>
      <abstract><![CDATA[Most generic editors have support for Markdown syntax and for many basic markdown editing tasks that might be fine. But if you're extensively working with Markdown on a regular basis it is constructive to use a dedicated Markdown editor that understands many common Markdown operations and can greatly simplify and speed them up as well as providing useful support features for linking and embedding. In this post I describe why I use a dedicated Markdown editor rather than a generic editor for my Markdown editing.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2017/Why-use-a-dedicated-Markdown-Editor/Banner.jpg</featuredImage>
    </item>
    <item>
      <title>Favorites for better Document Management in Markdown Monster</title>
      <description><![CDATA[Markdown Monster 1.12.6 introduces a new Favorites feature that makes it easy to add your most commonly used documents to a reusable list of file links. While this is nothing new for browsers, it's a somewhat novel idea for file management, especially when maintain a huge number of lists and notes with Markdown or other text content.]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2018/Jul/11/Favorites-for-better-Document-Management-in-Markdown-Monster</link>
      <guid isPermaLink="false">ksrnhkytcs3e</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2018/Jul/11/Favorites-for-better-Document-Management-in-Markdown-Monster#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2018/Jul/11/Favorites-for-better-Document-Management-in-Markdown-Monster</guid>
      <pubDate>Wed, 11 Jul 2018 09:01:05 GMT</pubDate>
      <abstract><![CDATA[Markdown Monster 1.12.6 introduces a new Favorites feature that makes it easy to add your most commonly used documents to a reusable list of file links. While this is nothing new for browsers, it's a somewhat novel idea for file management, especially when maintain a huge number of lists and notes with Markdown or other text content.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2018/Faovorites-in-Markdown-Monster/FavoritesInMarkdownMonster.png</featuredImage>
    </item>
    <item>
      <title>FolderBrowser Enhancements in Markdown Monster</title>
      <description><![CDATA[The latest version of Markdown Monster (v1.8.12) significantly upgrades the Folder Browser, turning it into a more capable file management hub. The update adds a modern UI with descriptive file icons, smarter navigation with autocomplete paths and environment variable support, and dynamic loading for improved performance in large folders. New productivity features include Find in Files, tighter drag-and-drop image support, and expanded Terminal, Explorer, and Git integration—making project asset management faster and more intuitive directly within the editor.]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2018/Jan/10/FolderBrowser-Enhancements-in-Markdown-Monster</link>
      <guid isPermaLink="false">c4k6wc8s8jk2</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2018/Jan/10/FolderBrowser-Enhancements-in-Markdown-Monster#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2018/Jan/10/FolderBrowser-Enhancements-in-Markdown-Monster</guid>
      <pubDate>Wed, 10 Jan 2018 12:00:00 GMT</pubDate>
      <abstract><![CDATA[The latest version of Markdown Monster (v1.8.12) significantly upgrades the Folder Browser, turning it into a more capable file management hub. The update adds a modern UI with descriptive file icons, smarter navigation with autocomplete paths and environment variable support, and dynamic loading for improved performance in large folders. New productivity features include Find in Files, tighter drag-and-drop image support, and expanded Terminal, Explorer, and Git integration—making project asset management faster and more intuitive directly within the editor.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2018/FolderBrowser-Enhancements-in-Markdown-Monster-1.8.12/PostBanner.jpg</featuredImage>
    </item>
    <item>
      <title>Creating a Markdown Monster Addin: Save Images to Azure Blob Storage</title>
      <description><![CDATA[The Markdown Monster Markdown Editor and Weblog Publishing tool has a .NET based addin model that makes it relatively easy to extend its core feature set with custom functionality. In this post I show how you can quickly create an addin of your own, and then show a practical example that demonstrates how add Image uploading to Azure Blob storage as an interactive addin.]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2017/Apr/17/Creating-a-Markdown-Monster-Addin-Save-Images-to-Azure-Blob-Storage</link>
      <guid isPermaLink="false">isunhapaf1jx</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2017/Apr/17/Creating-a-Markdown-Monster-Addin-Save-Images-to-Azure-Blob-Storage#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2017/Apr/17/Creating-a-Markdown-Monster-Addin-Save-Images-to-Azure-Blob-Storage</guid>
      <pubDate>Mon, 17 Apr 2017 12:00:00 GMT</pubDate>
      <abstract><![CDATA[The Markdown Monster Markdown Editor and Weblog Publishing tool has a .NET based addin model that makes it relatively easy to extend its core feature set with custom functionality. In this post I show how you can quickly create an addin of your own, and then show a practical example that demonstrates how add Image uploading to Azure Blob storage as an interactive addin.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2017/Creating-a-Markdown-Monster-Addin-Save-Images-to-Azure-Blob-Storage/PluginExtensions.jpg</featuredImage>
    </item>
    <item>
      <title>Getting Images into Markdown Documents and Weblog Posts with Markdown Monster</title>
      <description><![CDATA[One good justification for using a rich editor for editing Markdown or a Weblog entry is that you can provide some additional features above and beyond what a simple text or code editor can provide.  When you're creating content you are usually dealing with a number of things beyond plain text like code snippets, feature widgets and most importantly - **images**. Markdown Monster]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2017/Mar/14/Getting-Images-into-Markdown-Documents-and-Weblog-Posts-with-Markdown-Monster</link>
      <guid isPermaLink="false">yk57daadf8r3</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2017/Mar/14/Getting-Images-into-Markdown-Documents-and-Weblog-Posts-with-Markdown-Monster#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2017/Mar/14/Getting-Images-into-Markdown-Documents-and-Weblog-Posts-with-Markdown-Monster</guid>
      <pubDate>Tue, 14 Mar 2017 12:04:43 GMT</pubDate>
      <abstract><![CDATA[One good justification for using a rich editor for editing Markdown or a Weblog entry is that you can provide some additional features above and beyond what a simple text or code editor can provide.  When you're creating content you are usually dealing with a number of things beyond plain text like code snippets, feature widgets and most importantly - **images**. Markdown Monster]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2017/Getting-images-into-Posts-with-Markdown-Monster/PostBanner.jpg</featuredImage>
    </item>
    <item>
      <title>Introducing Markdown Monster - a new Markdown Editor</title>
      <description><![CDATA[I'm happy to announce Version 1.0 of Markdown Monster a Markdown Editor and Weblog Publishing tool for Windows. In this post I give a quick tour of Markdown Monster and provide links to all you need to know to check out this great new Markdown editor.]]></description>
      <link>https://markdownmonster.west-wind.com/blog/posts/2017/Feb/23/Introducing-Markdown-Monster-a-new-Markdown-Editor</link>
      <guid isPermaLink="false">2h5mvowifrb8</guid>
      <author> (Rick Strahl)</author>
      <comments>https://markdownmonster.west-wind.com/blog/posts/2017/Feb/23/Introducing-Markdown-Monster-a-new-Markdown-Editor#Comments</comments>
      <guid>https://markdownmonster.west-wind.com/blog/posts/2017/Feb/23/Introducing-Markdown-Monster-a-new-Markdown-Editor</guid>
      <pubDate>Thu, 23 Feb 2017 12:00:00 GMT</pubDate>
      <abstract><![CDATA[I'm happy to announce Version 1.0 of Markdown Monster a Markdown Editor and Weblog Publishing tool for Windows. In this post I give a quick tour of Markdown Monster and provide links to all you need to know to check out this great new Markdown editor.]]></abstract>
      <featuredImage>https://markdownmonster.west-wind.com/blog/imageContent/2017/Introducing-Markdown-Monster/MarkdownMonster.png</featuredImage>
    </item>
  </channel>
</rss>