<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-06-16T18:17:11.6559273Z</pubDate>
    <lastBuildDate>2026-06-01T21:54:24.6846996Z</lastBuildDate>
    <generator>Rick Strahl's West Wind Weblog</generator>
    <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>The warning dialog is one thing as it is a valid concern to warn people about installing software from unknown locations. But using provocative colors (blue screen anybody?), scary language and making the step around procedure un-obvious is to essentially scare people out of installing external software, which is a age-old staple of Windows usage.</p>
<p>It's a pain to users who often get scared away from installing software that is legitimate and it's a pain to developers who have to deal with lost users and the support that comes from questions around why the application won't install.</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 not likely 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 it's clearly designed to scare users out of installing apps not coming from the Windows Store.</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 if you download from the Web.</p>
<p>Make sure that if you do use the bypass described above you are familiar with the vendor and 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!</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 platforms review software before it's published, run malware checks and run through automated tests that check for successful installations and side effects. It's not full proof - but you do get at least some vetting of software.</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.</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.</p>
<p>This bypasses most of the SmartScreen security flags.
Here are a couple of examples you can run from the Windows Terminal:</p>
<pre><code class="language-ps">winget install MarkdownMonster
choco install DocumentationMonster
</code></pre>
<p>All of the managers include commands to update and list already installed components.</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. So there's some pre-validation happening by the provider that provides a better pre-requisite for security than 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. 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>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 - 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 as users that get SmartScreen'd can use it as an alternative that is likely to work better.</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>
<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 thourough 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>But what pisses me off though is that many users are sure they want to install, and perhaps have even installed a previous version of same software from the same site, and they are still warned away the same as everyone else. Often users don't know how to navigate past the scary blue dialog to install - most casual users are simply scared off.</p>
<p>The way that SmartScreen does this seems particularly nasty, clearly trying to scare users into not installing externally downloaded apps, and trying to push people to Windows Store installed apps which never are forced through this rigmarole.</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>
<p>Essentially SmartScreen is designed to scare users, without giving any useful information and worse using a limited and flawed algorithm that doesn't take into account actual usage or continuity using forced certificates. At this point it even seems that having an Authenticode Certificate on the installer has no retention value for reputation whatsoever, even or maybe especially when using Microsoft's own Trusted Signing support.</p>
<p>Having no certificate is still worse though, because unsigned installers automatically throw up SmartScreen regardless of reputation.</p>
<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.</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://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>
<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://www.amazon.com/dp/BT00LN946S?externalReferenceId=fdeaac92-deca-4ea5-92c1-442cdc15a646"  target="_blank"
		  title="Sign up for an Amazon Visa - 5% cash back for Amazon and Whole Food Purchases">
<img src="https://markdownmonster.west-wind.com/blog/images/sponsors/AmazonPrimeVisa-Display.jpg" 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[<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2021/Taking-down-the-Markdown-Monster-Source-Code/Denied.png" alt=""></p>
<p>With a heavy heart and a lot of hand wringing, I decided last week to take down the <a href="https://markdownmonster.west-wind.com">Markdown Monster</a> source code from the public GitHub repository due to rampant license abuses.</p>
<p>The GitHub repository is still there and will continue to be there. You can still download Markdown Monster installers and access the Chocolatey, Snap and WinGet packages. Issues will continue to be processed and fixed and new versions will be forthcoming. <strong>Markdown Monster is not dead!</strong></p>
<p>But the source code out in the open is now a thing of the past and only <a href="https://markdownmonster.west-wind.com/purchase#SourceCode">available by explicit request in a private repository</a>.</p>
<p>In this post I'll talk about the reasons for this action as well as offer some of my thoughts on the state of software today. You can take the latter with a grain of salt, but the discussion of the hows and whys of having source code in the open and how it didn't work out for me might be useful to others who are thinking about doing something similar.</p>
<h3 id="a-history-of-markdown-monster-as-a-product">A History of Markdown Monster as a Product</h3>
<p>Markdown Monster is a Windows based Markdown Editor and Weblog Publisher that provides a ton of functionality around the basic process of Markdown editing. It sounds simple enough, but to do Markdown right and provide a productive workflow for writing, there are a lot of things that you can do to make the process easier and Markdown Monster is my take on doing that. What started as a fairly minimal editor has transformed in a multi-functional application, that still provides a simple user experience while providing many sophisticated addon features. You can check out the features either on the <a href="https://markdownmonster.west-wind.com">Markdown Monster site</a> or on the <a href="https://github.com/RickStrahl/MarkdownMonster">GitHub repository</a>.</p>
<p>Markdown Monster started very modestly but has grown both in feature scope as well as popularity.</p>
<p>The project is not and never was a FOSS (Free Open Source) project. But it did have source code on GitHub out in the open, and uses a commercial license that requires a license purchase or use one of several avenues related to supporting the project to get a free license. Free licenses are offered to contributors (both code as well as feedback, help with tracking down bugs, or any other valuable support of Markdown Monster up to our discretion) as well to various developer programs and organizations. Discounted licenses are available depending on international locations.</p>
<p>When I started with Markdown Monster it was a very small project and licensing was mostly  an afterthought, but as time went on the product grew in sophistication, and today it is used by more than a thousand people every day on average. Supporting and updating Markdown Monster has become much more than just a small side project that I can work on for a few hours a week between adding new features, fixing bugs and fielding support for issues, feature requests and other minutiae.</p>
<p>From the very beginning I was pretty clear in my vision to <strong>not make this a free product</strong>. I have plenty of true FOSS open source projects where all code is open and free to use, but when it comes to building what ended up being a commercial  product as a one-man shop developer, the effort involved in development and support goes beyond what I can afford to just give away in time and effort, even in light of free competition from other editors that have big corporate backing or from small tools that are much less feature rich.</p>
<blockquote>
<p><strong>For me I was never about giving Markdown Monster away for free. If you don't like it - use something else!</strong></p>
</blockquote>
<h3 id="early-days">Early Days</h3>
<p>Initially - before there was a lot more interest - this dual distribution worked out well. Many people registered and played by the licensing rules. The source code got picked up in Forks and there also were a fair amount of small contributions in those early days.</p>
<p>The ratio between usage and registrations was reasonable at first. And <strong>thank you to all of you that did register</strong> - I really appreciate that, especially in light of all those that didn't later on.</p>
<p>Additionally, at the start at least, there was quite a bit of incoming support with code submissions, lots of feedback and suggestions, or simply working through features or bugs, which resulted in me giving out quite a few free licenses for helping along Markdown Monster to become a better product. I really want to thank those contributors as well - you've all helped make Markdown Monster a much better tool, and I really appreciate all the feedback and discussion. Many have resulted in new and useful features and enhancements that I would not have made on my own.</p>
<p>Over time though, as Markdown Monster has added many more features and the code has gotten more complex, that involvement has died down some, as the product has matured and found it's niche. But there are still many great feature requests and bug reports and that is also much appreciated. And there are still a number of people who frequently provide valuable feedback or other support that warrants free licenses.</p>
<p>I strongly believe in:</p>
<blockquote>
<p><em><strong>Give something, get back something. Value for value!</strong></em></p>
</blockquote>
<p>Whether that's with $$$ or feedback or time or promotion, I believe something should come back for use of software. And I'm not just talking about MM here, but in more general terms and especially for OSS projects.</p>
<h3 id="popularity-and-abuse">Popularity and Abuse</h3>
<p>But as Markdown Monster became yet more popular and I started looking at the logs it became quite obvious that the vast majority of users <strong>were not playing by the rules</strong>. The ratio between usage and registrations widened, and it was clear that hacked versions were running on fake registrations.</p>
<p>What sort of abuses am I talking about? Markdown Monster tracks anonymous usage statistics and those usage statistics tell a pretty ugly usage story. Markdown Monster is not a free product despite the fact the source code was available on GitHub.</p>
<p>Here are some numbers from some of the recent logs:</p>
<ul>
<li>More than 1000 people use Markdown Monster daily on average</li>
<li>Of users having used MM more than 50 times - less than 1 in 180 is registered</li>
<li>Of users having used MM more than 20 times - less than 1 in 400 is registered.</li>
<li>Lots of first time accesses with 'Registered' status from locations that have never registered</li>
</ul>
<p>For example, there are tons of users in India, China and Russia that show with registered status. Just checked I have 1 registration from China, none from Russia and 2 from India. Clearly somebody's not playing by the rules.</p>
<p>This despite the fact that some time ago I'd set up options for reduced pricing for international locales to make pricing more in in-line with local income. I've offered <a href="https://markdownmonster.west-wind.com/purchase#discountpricing">reduced pricing for licenses in different locales</a> based on the <a href="https://fxssi.com/big-mac-index">Big Mac Index</a> which assigns percentage discounts based on the locale by request. I put this program up late last year (8 months ago) - to date I had <strong>two requests</strong> for the discount and <strong>one order</strong> from it. IOW, nobody gives a shit... because free is always better than cheap, right?</p>
<p>There are also free license offers for Microsoft MVPs, Microsoft Employees, any company that provides free stuff into the MVP program - which is my way of giving back something to that program and those companies that have provided access to tools and software to me over the years. There's generous use of that and that's fine - that's the way it was designed to be.</p>
<p>What I'm trying to get at here is that I've tried to make licenses accessible and give options to make it fair for both sides.</p>
<p>Give something and get something back.</p>
<p>I get it that some will still think a purchased license is too much <strong>because you know this other product is free</strong>. Fair enough, use that product if that works for you. But that's usually not how that goes. Instead it's use a hacked version and use the non-free product anyway despite not paying for it.</p>
<p>The very worst of it though, is that running the logs also showed me several different <strong>re-branded versions of Markdown Monster</strong> running under a different name. These people are so lazy they didn't even bother to remove the logging code.</p>
<p>As with all piracy you can make life miserable for everyone, and still not suppress all piracy, so I was opting for trying to make this work with minimal security and requirements and source code out in the open 😄</p>
<p>I'm not so naive to think that some of this wasn't going to happen. I've sold software throughout my professional life and have seen it all before - the ripped versions, and software keys etc. In most previous cases the lenient registration requirements worked out for the most part - most legit users that used the product beyond the trial periods or basics usually end up registering. However Markdown Monster serves a more general audience than my otherwise more business/corporate oriented software, and the the scale of license abuse in MM was something that I didn't expect. Rampant is the word and it's not an exaggeration in this case.</p>
<p>To be clear, I have no one else but myself to blame. It was a conscious choice to keep it simple and open when I started, being optimistic that users would see the value in that for everybody involved, but I was proven naive to think a different, optimistic outcome was going to come from this.</p>
<h3 id="thank-you-to-those-of-you-that-played-by-the-rules">Thank you to those of you that played by the Rules</h3>
<p>To be fair there have been also many registrations to Markdown Monster. Many users did play by the rules. And many people have either contributed, made a valuable feature request, or have taken the time to report a bug and followed through the sometimes time consuming process of tracking down a bug.</p>
<p>I want to thank you and provide a glimmer of hope that maybe I'm not a completely hopeless idealist. I really appreciate the support and those of you that have played by the rules that are a huge incentive to continue working on Markdown Monster and improving it going forward.</p>
<h3 id="pull-it">Pull it!</h3>
<p>So as a result of this abuse, I've been contemplating to tamp down on the rampant license abuse by removing Markdown Monster's source code. Having the source code available makes it just too easy to hack the code,  remove the licensing or as some have obviously done, completely re-brand Markdown Monster.</p>
<p>I've been contemplating this move for quite some time. Before actually going ahead with it, I wanted to see what kind of reaction I'd get and started off with this tweet from people that I regularly interact with on Twitter:</p>
<p><a href="https://twitter.com/RickStrahl/status/1382138098117615618"><img src="https://markdownmonster.west-wind.com/blog/imageContent/2021/Taking-down-the-Markdown-Monster-Source-Code/OriginalTweet.png" alt=""></a></p>
<p>I was expecting push back and being talked out of going forward.</p>
<p>Instead, surprisingly I got an earful of feedback and a bunch of co-miseration by other developers who had similar stories with code out in the open. The feedback was mostly along the lines  &quot;Yeah that sucks, but do what's right for you&quot;, which frankly I did not expect.</p>
<p>If you're interested you can follow the <a href="https://twitter.com/RickStrahl/status/1382138098117615618">discussion on the tweet</a> - there are a lot of insightful comments on this very long thread.</p>
<h3 id="going-going-gone">Going, Going... Gone</h3>
<p>After this discussion and some more soul searching I ended up pulling the plug and removing the source code - it's now gone from the main <a href="https://github.com/rickstrahl/MarkdownMonster">Markdown Monster GitHub repo</a>. The code of course is still there in archives for older versions and that's fine. That ship has long sailed for v1. But going forward the code is no longer out in the open.</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2021/Taking-down-the-Markdown-Monster-Source-Code/AaronNoMoreFreeForYou.png" alt=""></p>
<p><a href="https://markdownmonster.west-wind.com/download">Version 2.x</a> which is getting close to release will use a different licensing scheme that ties users and usage to specific keys and source code for that version will not be available. This adds more complexity, both on my end for license management as well as for end users who now have to enter long license keys and have to manage licenses for multiple machines.</p>
<p>Of course, Markdown Monster is a .NET app and .NET can easily be decompiled so code ripping isn't really a solved problem, but at least without source code so readily available there's a bit more of a hurdle than simply re-appropriating the application with a few quick code changes.</p>
<h3 id="source-code-loss-sucks">Source Code Loss Sucks</h3>
<p>It's a real bummer for me to kill the code too, as I have often used Markdown Monster source code as examples for blog posts and articles. Not only does the code removal break a lot of old code links, but it also removes easy issue linking on GitHub and quick back references to source code from the GitHub Issues Tracker. It also makes it harder for those that want to contribute and I'm sorry for that, but if you want to contribute or even just play with the source code you can request access to the now private Markdown Monster Code Repository. The private report allows me more control over who has access and weeds out the riff raff to some degree. It turns out with request access few are interested which is both a blessing and a curse.</p>
<h2 id="markdown-monster-is-not-dead">Markdown Monster is not Dead!</h2>
<p>I want to be very clear here: Although I cut off the source code in the <a href="https://github.com/RickStrahl/MarkdownMonster">GitHub repository</a>:</p>
<p><strong>Markdown Monster will continue as product just as it did before</strong></p>
<p>This change has very little impact on 99% of you using Markdown Monster. Unless you were one of the very few people using the source code - legitimately or otherwise - this has no impact on you at all.</p>
<p>I will continue to work on Markdown Monster, just as I did before, pushing out frequent updates, responding to issues on GitHub, fixing bugs and updating the various distribution points for Markdown Monster.</p>
<p>If you own a license - thank you I really appreciate your support!!! And your license is still good and continues to work just as it did before and you'll continue to get updates of the current major version for free, just as before.</p>
<p>If you don't own a license, the evaluation version continues to work the same as before too: You'll get the same fully functional version of Markdown Monster with the occasional nag screens and notices and a few features that are not accessible.</p>
<h3 id="source-code">Source Code</h3>
<p>The only thing that changes as of March 14th, 2020 is that the source code is no longer available in public.</p>
<p>The <a href="https://github.com/RickStrahl/MarkdownMonster">GitHub repository</a> is still up and continues to serve for issue tracking and as a secondary product landing page that contains download, installation and feature links.</p>
<p>But this repository is now devoid of a <code>Src</code> or <code>MarkdownMonster</code> folder that used to contain the source code.</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2021/Taking-down-the-Markdown-Monster-Source-Code/RepoNoSource.png" alt=""></p>
<p>There are still many forks of Markdown Monster out there but those forks will no longer track the live code going forward which now resides in a private repository.</p>
<p>I would much prefer to build Markdown Monster out in the open, but due to the rampant abuse keeping a public repository simply makes it too easy for the shit heads to abuse their privilege.</p>
<p>And for those that want to work with the Markdown Monster code for internal use, or to help improve Markdown Monster, it's possible to <strong>request private access</strong> to the GitHub repository. There's <a href="https://markdownmonster.west-wind.com/purchase#SourceCode">more info on the licensing page</a> on how to go about that.</p>
<h3 id="regretabble">Regretabble</h3>
<p>While I hate to do this and it is more work for me, private access at least allows me some control over who has access and if the abuse continues I can easily shut off either individual accounts or if necessary every one. We'll see.</p>
<p>As much as I prefer having things out in the open, it wasn't much of a benefit to have the source available during the 4 years of Markdown Monsters time so far. Early on there were a few strong contributions, but as the product has matured that has fizzled. I'm not surprised as Markdown Monster is not exactly trivial to work on. The source is not the easiest to navigate especially anything that has to do with UI.</p>
<p>I'm not complaining: For MM I actually prefer feature requests that I end up implementing unless it's something altogether out of my realm of capability or desire to build. For maintenance it's usually much easier for me to write the code and maintain it long term and streamline it into the overall Markdown Monster application flow.</p>
<p>But I do really regret having the code not in the open. There are so many benefits of having code available to reference. There are lots of small useful code blocks that I've shared over the years (and many more that I have not) that can be useful to others as well as myself for linking or referencing in posts, articles or other online content.</p>
<p>As always it's a few bad apples spoiling the goodwill for everyone else, but I don't know what other options I have if I want MM to continue as a licensed product.</p>
<p>So here we are. It's been a couple of months now since I pulled the source and there has been an uptick in registrations. The flow of incoming orders is definitely more steady and if v2 is an indication a lot of v1 users feel it's worth upgrading to the newer version as well. Again I appreciate those that do play by the rules.</p>
<h2 id="some-thoughts-the-state-of-software">Some Thoughts the State of Software</h2>
<p>I'm really sad that it's come to this. As I mentioned I wasn't blind to the idea that this was going to happen but with the initial release I was trying to be cautiously optimistic that this open but licensed concept could work. And in fact it did for the first 2 years or so before Markdown Monster started getting popular.</p>
<p>I've been doing software sales for a loooong time and there's no denying that the trend of commercial value in software is slowly inching its way toward zero. Open Source has done us no favors in that respect as that perpetuates the idea that you can get something for nothing. Some people end up doing all the work while many more do nothing to support the cause and just take without giving something back. There's no value for value proposition there for most participants.</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2021/Taking-down-the-Markdown-Monster-Source-Code/AaronOssIsLikeWildLands.png" alt=""></p>
<p>I think there's a big problem with anything that is free. It is a price distortion, because effectively nothing is free. There's always a price associated with anything to create it or on the flip-side, to use it. The price may be hidden or spread out, or worse yet delayed and to be paid back in hidden benefits that aren't obvious. And without a price the value of the item is often easy to just throw away both from the perspective of the user as well as the developer.</p>
<p>Add to that big vendors giving away sophisticated software for free. Visual Studio, VS Code many other editors and IDEs, lots and lots of tools, libraries etc. Think about all the free stuff that we all use everyday - how much have any of us given back to many of those free tools we use? But there's often a catch. Embedded marketing, data collection, etc. etc. all exacts a price.</p>
<p>I'm not immune to subconsciously leaning toward free software either.  Even though I go through my list of tools and libraries occasionally to give back something I never end up going through everything - there's too much of that. It's neither obvious, consistent and too often it just gets forgotten and omitted altogether, if not willfully then accidentally.</p>
<p>Honestly the honor system is a lot of work. As a user who actually honors the unwritten contract you have to try to figure out what the thing you're using is worth. And usually we are very likely to err on the downside would be my guess. It takes some effort to do the right thing, to remember to do this every year or every few years. Did you remember to do your part when it was time? For the developer it's an effort too, because they have to incentivize and advertise that 'feature' and try to convince user to contribute in some way when they can effectively ignore the plea altogether. It's a lot of wasted mental energy by comparison to setting a fixed value for what the software is worth in the first place.</p>
<p>After a while we've all been conditioned that the software we do use should be free or at minimum dirt cheap. How often do we all run around looking for something we need and opt for the often inferior solution just because it is free?</p>
<p>As a result we often end up centralized solutions because all resources pour into only the biggest projects that have support from huge numbers of developers, or from huge corporations that control popular open source projects (Microsoft, Google, Facebook, Amazon etc.) by having paid developers doing full-time work 'open source' project.</p>
<p>For smaller developers open source rarely draws enough resources to subsidize a project either financially or via contributions or support. Instead those are the projects that are usually taken advantage of the most. Too small to be taken serious, and overlooked when it comes to supporting when the time comes to pay up or offer up donations/support for OSS solutions. Again, I'm not immune that problem myself and guilty as charged myself! It's the nature of the beast.</p>
<p>What I'm trying to get at that free is a distortion that changes your relationship with the tools you use. It becomes a throwaway thing both for users and developers. If the tool doesn't work users are bound to walk away instead of helping improve it because the assumption is that it has no value. Move on to the next no value thing.</p>
<p>If the developer gets tired of the tool or finally figures out that he's busting his balls for no pay back, he may just decide to walk away without looking back potentially leaving users hanging. Been there done that a couple of times myself too - not proud but had to do it to keep my sanity.</p>
<p>Putting a price on something makes that a lot harder - first because the developer owes something to those that have spent money, and secondly because the $$$ provide at least some incentive to continue on. The user has invested some $$$ too and wants to get her money's worth. A $$$ price also helps crystallize whether there is real value in a project - if it's not free would people still be willing to use it? With free you often never know if it's because your tools are good, or whether it's just because it's free.</p>
<p>I mention all this in context of Markdown Monster, because it is not a free tool and it has to fight the free stigma. I totally get the aversion to non-free and that's fine. If that's not for you - use something else. But what really flummoxed me with this particular product was  that it wasn't shunned, but actively subverted to work around the non-free implementation.</p>
<p>The reality is as a small single developer building a real, licensed product, it is difficult to survive on. Markdown Monster is a not a big project and it plays in an area with quite a bit of competition. But yet it's quite popular and there are a lot of users who use it heavily every day myself included. Even if most users would play by the license rules, it still wouldn't be enough to support even myself as a single developer. But it helps in keeping at it.</p>
<p><img src="https://markdownmonster.west-wind.com/blog/imageContent/2021/Taking-down-the-Markdown-Monster-Source-Code/Pushback.png" alt=""></p>
<p>I have other things going to support myself, while Markdown Monster is one of many side projects I maintain and work on in rotation. Yet because of the popularity more and more of my time ends up being spent in MM to fix bugs, deal with issues and questions and general support. It it worth it? Financially, not by country mile! If I count up the time I've spent vs. the payout I would barely qualify for US minimum wage. For the joy of building this product?  Yeah - MM is probably the best thing I've built in my long career of tools I've created all the way back to the mid-nineties. There's a certain pride in that and quite frankly it's been the most fun project I've worked on in a really long time. As a heavy user of MM I also have a keen interest in making it the best that it can be.</p>
<p>So for now, time marches on. Version 2.x is about to release with some changes in registration and licensing, no source code and I'll find out how it goes. I'm sure the lack of code (even if available by requested access) might drive off some people, but if it ends up driving off people who were never going to play by the licensing rules anyway, then maybe it's not a big loss.</p>
<p>We shall see.</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/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>