{"id":15486987,"url":"https://github.com/rickstrahl/westwind.web.markdown","last_synced_at":"2025-04-22T16:27:03.479Z","repository":{"id":66331243,"uuid":"103388662","full_name":"RickStrahl/Westwind.Web.Markdown","owner":"RickStrahl","description":"Markdown support for ASP.NET WebForms and MVC applications","archived":false,"fork":false,"pushed_at":"2019-11-11T23:52:04.000Z","size":3415,"stargazers_count":19,"open_issues_count":0,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-13T12:05:17.591Z","etag":null,"topics":["aspnet","aspnet-mvc-5","csharp","markdown","webforms"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RickStrahl.png","metadata":{"files":{"readme":"readme.md","changelog":"Changelog.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["RickStrahl"],"custom":"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=K677THUA2MJSE\u0026source=url"}},"created_at":"2017-09-13T10:54:46.000Z","updated_at":"2023-06-14T03:16:31.000Z","dependencies_parsed_at":"2023-02-20T19:45:43.871Z","dependency_job_id":null,"html_url":"https://github.com/RickStrahl/Westwind.Web.Markdown","commit_stats":null,"previous_names":["rickstrahl/westwind.web.markdowncontrol"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Web.Markdown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Web.Markdown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Web.Markdown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RickStrahl%2FWestwind.Web.Markdown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RickStrahl","download_url":"https://codeload.github.com/RickStrahl/Westwind.Web.Markdown/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250276303,"owners_count":21403840,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aspnet","aspnet-mvc-5","csharp","markdown","webforms"],"created_at":"2024-10-02T06:20:42.089Z","updated_at":"2025-04-22T16:27:03.460Z","avatar_url":"https://github.com/RickStrahl.png","language":"C#","funding_links":["https://github.com/sponsors/RickStrahl","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=K677THUA2MJSE\u0026source=url","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=3RZRUFCWD24R4"],"categories":[],"sub_categories":[],"readme":"# Westwind.Web.Markdown\n#### Markdown Support for your System.Web based ASP.NET WebForms and MVC applications\n\n\n## Get it from NuGet\nTo use the control you can install from [Nuget](https://www.nuget.org/packages/Westwind.Web.Markdown/):\n\n```ps\nPS\u003e install-package Westwind.Web.Markdown\n```\n\n## Features\nThis library provides:\n\n* **Markdown Parser Functions**  \nSimple Markdown Parsing with `Markdown.Parse()` and `Markdown.ParseHtml()` methods you can use in code or in your MVC or WebForms markup.\n\n* **Markdown WebForms Control for 'Markdown Islands'**  \nA useful `\u003cww:markdown\u003e` server WebControl for easily embedding static Markdown text, Markdown from a file or data-bound Markdown into a document. Great for using Markdown for static content inside of larger Web Pages including the ability to load content from file.\n\n* **Serve Markdown Pages from Disk using MarkdownHttpHandler**  \nThis Http handler allows you to drop Markdown files into a site and serve those Markdown files as HTML rendered into a configurable template. The template's job is to provide the site chrome around the HTML so this can simply be a small content page pointing a Master Page in WebForms or Layout Page in MVC. A model object is passed via the Items collection.\n\n* **Uses the the awesome Markdig Parser**  \nThis library relies on the [Markdig](https://github.com/lunet-io/markdig) Markdown Parser and provides access to all Markdown Pipeline configuration options of that parser via a configuration hook.\n\n* **Optional Html Script Sanitation**  \nBoth the parsers and Web Control have options to sanitize HTML to avoid common XSS attacks.\n\n## Static Markdown Parsing Functions\nFor direct Markdown parsing you can use this library for rendering Markdown to HTML as strings or `HtmlString` values for MVC.\n\n```cs\nstring html = Markdown.Parse(\"This is **bold Markdown**.\");\n```\n\nor\n\n```html\n\u003c%= Markdown.Parse(\"This is **bold Markdown**.\") %\u003e\n```\n\nor even this in WebPages or MVC:\n\n```cs\n@Markdown.ParseHtml(\"This is **bold Markdown**.\")\n```\n\nThere are also a couple of file based methods that parse Markdown from files:\n\n\n```html\n\u003c%= Markdown.ParseHtmlFromFile(\"~/HomePageMainContent.md\") %\u003e\n```\n\nor in MVC:\n\n```html\n@Markdown.ParseHtmlStringFromFile(\"~/HomePageMainContent.md\")\n```\n\n\n## Markdown Control\nThe Web Control provides you the abililty to easily embed static Markdown text into any Web Forms page.\n\n```html\n\u003cww:Markdown runat=\"server\" id=\"md1\"\u003e\n    ### 1.6.2\n    *September 10th, 2017*\n    \n    * **Keyboard support for Context Menu**  \n    You can now pop up the context menu via keyboard using the Windows context menu key (or equivalent). The menu is now cursor navigable. This brings spell checking and various edit operations to keyboard only use.\n    \n    * **Fix: `UseSingleWindow=false` no longer opens Remembered Documents**   \n    When not running in `UseSingleWindow` mode, the `RememberLastDocumentsLength` setting has no effect and no previous windows are re-opened. This is so multiple open windows won't open the same documents all the time. In `UseSingleWindow` mode last documents are remembered and opened when starting MM for the first time.\n\u003c/ww:Markdown\u003e\n```\n\nAnd the content will be rendered to HTML at runtime.\n\n\n## Control Usage and Syntax\nTo use the control add it to your page like any other server control.\n\nFirst add a reference to the control assembly either on the page or in Web.config:\n\nAt the top of the page:\n```html\n\u003c%@ Register TagPrefix=\"ww\" Namespace=\"Westwind.Web.Markdown\" Assembly=\"Westwind.Web.Markdown\" %\u003e\n```\n\nor in `web.config` globally:\n\n```xml\n\u003cconfiguration\u003e\n    \u003csystem.web\u003e\n        \u003cpages\u003e\n            \u003ccontrols\u003e\n                \u003cadd assembly=\"Westwind.Web.Markdown\" \n                     namespace=\"Westwind.Web.Markdown\" \n                     tagPrefix=\"ww\" /\u003e\n            \u003c/controls\u003e\n        \u003c/pages\u003e\n    \u003c/system.web\u003e\n\u003c/configuration\n```      \n\nThen embed the control into the page where you want the markdown to appear:\n\n```xml\n\u003cww:Markdown runat=\"server\" id=\"md2\" \n             NormalizeWhiteSpace=\"True\"\n             Filename=\"\"\n             SanitizeHtml=\"True\"\u003e\n    # Markdown Monster Change Log \n    [download latest version](https://markdownmonster.west-wind.com/download.aspx) \u0026bull; \n    [install from Chocolatey](https://chocolatey.org/packages/MarkdownMonster) \u0026bull; \n    [Web Site](https://markdownmonster.west-wind.com)\n\u003c/ww:Markdown\u003e\n```\n\n#### NormalizeWhiteSpace\nThis property is true by default and if the control starts with a line that is indented it will strip the same indentation from all lines following. This allows text like this to render properly as Markdown:\n\n```html\n\u003cdiv class=\"container\"\u003e\n    \u003cww:Markdown runat=\"server\" id=\"md1\"\u003e\n        ### 1.6.2\n        *September 10th, 2017*\n        \n        * **Keyboard support for Context Menu**  \n        You can now pop up the context menu via keyboard using the Windows context menu key (or equivalent). The menu is now cursor navigable. This brings spell checking and various edit operations to keyboard only use.\n        \n        * **Fix: `UseSingleWindow=false` no longer opens Remembered Documents**   \n        When not running in `UseSingleWindow` mode, the `RememberLastDocumentsLength` setting has no effect and no previous windows are re-opened. This is so multiple open windows won't open the same documents all the time. In `UseSingleWindow` mode last documents are remembered and opened when starting MM for the first time.\n    \u003c/ww:Markdown\u003e\n\u003c/div\u003e\n```\n\nNotice the indentation of the markdown.  With `NormalizeWhiteSpace` off you need to explicitly left align the embedded Markdown Content:\n\n```xml\n\u003cww:Markdown runat=\"server\" id=\"md2\" NormalizeWhiteSpace=\"False\"\u003e\n# Markdown Monster Change Log \n[download latest version](https://markdownmonster.west-wind.com/download.aspx) \u0026bull; \n[install from Chocolatey](https://chocolatey.org/packages/MarkdownMonster) \u0026bull; \n[Web Site](https://markdownmonster.west-wind.com)\n\u003c/ww:Markdown\u003e\n```\n\nIf not normalized the entire markdown block would render as code (more than 4 white space characters which is a code block). When `NormalizeWhiteSpace` is true the leading space is stripped of the entire block.\n\n\u003e #### First Line Determines Whitespace to strip\n\u003e The first line of the Markdown block determines what white space is stripped from all other lines.\n\nNote the default is `True` - if you have funky behavior due to indentation I'd recommend you left justify your markdown and set this value to `False`.\n\n#### SanitizeHtml\nMarkdown is essentially a superset of HTML as you can embed any HTML into Markdown. Markdown itself doesn't have any rules about what HTML can be embedded and it's entirely possible to embed script code inside of markdown.\n\nIf you capture Markdown text from users it's important **you treat input Markdown just as you would raw HTML user input**.\n\nTo help with this, the Markdown control has a `SanitizeHtml` property which is **set to `True` by default**, which performs rudimentary script sanitation. It removes `\u003cscript\u003e`, `\u003ciframe\u003e`, `\u003cform\u003e` and a few other elements, removes `javascript:` and `data:` attribute content, and removes `onXXX` event handlers from HTML input.\n\nIf you rather render your Markdown *as is* set `SantizeHtml` to `False`. To see what that looks like you can try the following in your Markdown block:\n\n\n```html\n\u003cmarkdown runat=\"server\" id=\"mm1\" \n          SanitizeHtml=\"False\"\u003e\n\t\n\t### Links:\n\t[Please don't hurt me](javascript:alert('clicked!');)\n\t\n\t### Script Blocks\n\t\u003cscript\u003ealert('this will show!');\u003c/script\u003e\n\t\n\t\u003cdiv onmouseover=\"alert('That really hurts!')\"\n\t     style=\"opacity: 0; padding: 20px;\"\u003e\n\t\tA hidden menace in Venice\n\t\u003c/div\u003e\n\u003c/markdown\u003e\n```\n\nBoth `Markdown.Parse()` and `Markdown.ParseHtml()` also have a sanitizeHtml parameter that is `true` by default.\n\nIf you render static text you control then `SanitizeHtml=False` is usually Ok, but if you take user input and put into the browser to display, **always use `SanitizeHtml=True`**.\n\n#### Filename\nYou can optionally provide a file name in lieu of text content in the Markdown control body. Files can be specified as virtual paths:\n\n```html\n\u003cww:Markdown  Filename=\"~/EmbeddedMarkdown.md\"\u003e\u003c/ww:Markdown\u003e\n```\n\nThe file name is resolved and loaded from disk, converted into Markdown and rendered into the page.\n\nThe file name is fed to `Server.MapPath()` so any path that is valid for `MapPath()` will work, but for portability I recommend you either use a page relative path or a virtual path as shown above.\n\n\u003e #### Related Resources are Host Page relative\n\u003e Please not that resources linked in the Markdown document - images mostly - are **host page** relative, not relative to the Markdown file. In most cases it'll be best to place referenced Markdown documents in the same folder as the host page to ensure that relative links work consistently.\n\n### Static Markdown Rendering\nThe control also includes static Markdown rendering that you can use in your Web Application inside of pages or your Web code.\n\n```cs\nstring html = Markdown.Parse(\"This is **bold Markdown**\");\n```\n\nYou can also embed Markdown into pages like this:\n\n```html\n\u003cdiv class=\"container\" id=\"ChangeLogText\"\u003e\n    \u003c%= Markdown.Parse(Model.ChangelogMarkdownText) %\u003e\n\u003c/div\u003e    \n```\n\nor in WebPages or MVC:\n\n\n```html\n\u003cdiv class=\"well well-sm\"\u003e\n    @Markdown.ParseHtml(\"This is **bold Markdown**.\")\n\u003c/div\u003e\n```\n\n#### sanitizeHtml Parameter\nBy default the Parse method applies HTML sanitation via a `sanitzeHtml` parameter, which defaults to `true`. If you would like to get the raw unsanitized HTML returned or you want to do your own HTML Sanitation post parsing, set `sanitizeHtml: false` in the method call.\n\nFor code you know is safe:\n\n```cs\nstring html = Markdown.Parse(staticMarkdown,sanitizeHtml: false);\n```\n\nFor user input that you echo back to the screen:\n\n```cs\n// true is the default but it's good to be explicit!\nstring html = Markdown.Parse(staticMarkdown, sanitizeHtml: true);\n```\n\n\u003e #### Important\n\u003e Always treat user entered Markdown as you would raw HTML!\n\n\n\n## Markdown Page Handler\nThe Markdown HTTP Handler allows you to simply drop Markdown files into an ASP.NET Web site and get those pages served as HTML. You can provide a template to provide the site's chrome around the rendered and access a 'model' that contains the title, the rendered Markdown,  original Markdown and a few other things to render into your template. The 'template' is simply an endpoint in your System.Web based application, so it can point at either a **WebForms Page** or an **MVC Controller/View Endpoint**.\n\n### Setting up the Markdown Page Handler\nTo set up the handler you need to:\n\n* Add a reference to Westwind.Web.Markdown Nuget package\n* Add a Handler mapping of `.md` to `MarkdownHttpHandler`\n* Set up a 'template' HTML page or Controller/View\n* Use `Context.Items[MarkdownHttpHandler.ItemKey] to retrieve the model\n* Embed `Model.RenderedMarkdownHtml` into the template\n* Drop some `.md` files anywhere in your site\n\n### Add an HttpHandler Mapping\nIn order for IIS and ASP.NET to process `.md` (or whatever other extensions you choose) files, the extension has to be registered in `web.config`.\n\n```xml\n\u003cconfiguration\u003e\n  \u003csystem.webServer\u003e\n    \u003chandlers\u003e      \n      \u003cadd name=\".md extension\" \n           path=\"*.md\" verb=\"GET\" \n           type=\"Westwind.Web.Markdown.MarkdownHttpHandler,Westwind.Web.Markdown\" \n           preCondition=\"integratedMode\" /\u003e\n    \u003c/handlers\u003e\n  \u003c/system.webServer\u003e\n\u003c/configuration\u003e\n```\n\n### Configuration \nYou can optionally configure the handler's operation using the static configuration object provided as `MarkdownHttpHandler.Configuration`. Preferrably you'll want to set this configuration once during application startup in `Application_Start()`:\n\n```cs\nvoid Application_Start(object sender, EventArgs e) \n{\n\tMarkdownHttpHandler.Configuration.SanitizeHtml = true;\n\tMarkdownHttpHandler.Configuration.MarkdownTemplatePagePath = \"~/_MarkdownPage.aspx\";\n}\n```\n\nBoth of these values are shown as default above so unless you need to change those values you don't have to set them. The important one is the virtual path to the template that will actually render the Markdown content as a full HTML document. This can be any valid page in your `System.Web` based Web site that can access the `Context.Items` collection which is needed to retrieve the model data.\n\n### Create a Template\nNext you'll need a template into which the markdown content can be rendered. Remember Markdown is just an **HTML Fragment** not a full document, so Markdown always needs a host document. Most likely you'll also want to make sure the document renders consistently using your Web site's consistent site chrome.\n\nYou can use either WebForms or MVC to do this - just pick an WebForms page or MVC view as an endpoint and then access the following model data in your HTML markdown or codebehind/controller:\n\n```cs\nvar model = Context.Items[MarkdownHttpHandler.ModelKey] as MarkdownModel;\n```\n\nThe model's properties available look like this:\n\n| Property         | Value                                    |\n|------------------|------------------------------------------|\n| Title            | The title of the page from first # header or YAML |\n| RenderedMarkdown | An HtmlString value that contains the rendered Markdown |\n| RawMarkdown      | Holds the raw, original Markdown text    |\n| YamlHeader       | Hold the YAML header if one is provided  |\n| RelativePath     | The relative virtual path of the original Markdown File |\n| PhysicalPath     | The physical path of the original Markdown File requested |\n\n\nMost likely the only values you'll be interested in are `RenderedMarkdown` and the `Title`. You'll want to use the title for the title in the `\u003chead\u003e` of the page at least, and perhaps also in some sort of non-content page header.\n\nHere's what the simplest possible templates look like for Web Forms and MVC:\n\n#### WebForms\n\n```html\n\u003c%@ Page Language=\"C#\" AutoEventWireup=\"true\" MasterPageFile=\"~/MasterPage.master\"  %\u003e\n\u003c%@ Import Namespace=\"Westwind.Web.Markdown\" %\u003e\n\n\u003casp:Content runat=\"server\" ContentPlaceHolderID=\"MainContent\"\u003e\n    \u003c%\n        var model = Context.Items[MarkdownHttpHandler.ModelKey] as MarkdownModel;\n    %\u003e\n    \u003cdiv class=\"container\"\u003e                \n        \u003c%= model.RenderedMarkdown %\u003e\n    \u003c/div\u003e\n\u003c/asp:Content\u003e   \n```\n\n#### MVC\nFor MVC you'll want to change the path to point a view/controller of your choice in the configuration in `Application_Start()`:\n\n```cs\n// this will be an internally redirected URL only\nMarkdownHttpHandler.Configuration.MarkdownTemplatePagePath = \"~/system/markdownhandling\";\n```\n\nThen you can have a controller method (or just code in a view):\n\n```\npublic ActionResult MarkdownHandling()\n{\n\tvar model = Context.Items[MarkdownHttpHandler.ModelKey] as MarkdownModel;\n\treturn View(model);\n}\n```\n\nThen inside of the Razor view you can utilize the model as needed:\n\n```html\n@model MarkdownModel\n\n\u003cdiv class=\"container\"\u003e\n\t\u003cdiv class=\"page-header\"\u003e\n\t\t@model.Title\n\t\u003c/div\u003e\n\n\t\u003cdiv class=\"page-content\"\u003e\n\t\t@model.RenderedMarkdown\n\t\u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003e If you need to pass other items into the view like authentication or login data required in your site chrome, you can just create a custom view that includes theMarkdownModel data. I left this in raw form from the `Context.Items` collection to allow this to work in just about any `System.Web` based solution. \n\nTemplates most likely will be very simple and only embed the content and title. All the rest of the page chrome is likely to be picked up by Master or Layout pages.\n\n### Dropping Files into your Site\nAt this point you can just drop `.md` files into your site. The files should be routed to the `MarkdownHttpHandler` which in turn renders the Markdown to HTML and calls your template with the `Context.Items` item that contains the model, which is then rendered by your customized template.\n\nThis is great to add some documentation or other text heavy content to your site.\n\n\n## Customizing the Markdown Pipeline\nThis parser uses the MarkDig Markdown parser which supports creating a custom pipeline. By default the parser is configured with most add-on features enabled. if you want to explicitly customize this list - either to minimize for performance, or for additional features you can override the static `MarkdownParserMarkdig.OnCreateMarkdigPipeline` function during application startup.\n\nWhen this `Func\u003cbool,MarkdigPipeline\u003e` is set, this function is called instead of the default pipeline build logic.\n\nCall this during application startup since the parser gets cached after first access. A good place as part of `Application_Init` processing:\n\n```cs\nvoid Application_Start(object sender, EventArgs e)\n{\n    // OPTIONAL - override parser pipeline addins\n    MarkdownParserMarkdig.OnCreateMarkdigPipeline = (usePragmaLines) =\u003e\n    {\n        var builder = new Markdig.MarkdownPipelineBuilder()\n            .UseEmphasisExtras()                \n            .UsePipeTables()\n            .UseGridTables()\n            .UseAutoLinks() // URLs are parsed into anchors\n            .UseAutoIdentifiers(AutoIdentifierOptions.GitHub)                \n            .UseYamlFrontMatter()\n            .UseEmojiAndSmiley(true);\n\n        if (usePragmaLines)\n            builder = builder.UsePragmaLines();\n\n        return builder;\n    };\n\n}\n```\n\nNote that the parser is cached so if you change this value anywhere but in startup code, you can explicitly force the parser to refresh with:\n\n```cs\nMarkdown.Parse(\"ok\",forceReload: true);\n```\n\n### Adding Code Highlighting\nIf you'd like to highlight your code snippets with syntax highlighting I recommend [Highlight.js](https://highlightjs.org/). Using this easy to use library you can add the following to a page to get syntax coloring for code snippets:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/dracula.min.css\" /\u003e\n\u003cscript src=\"//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js\"\u003e\u003c/script\u003e\n\n\u003cscript\u003e\n    function highlightCode() {\n        var pres = document.querySelectorAll(\"pre\u003ecode\");\n        for (var i = 0; i \u003c pres.length; i++) {\n            hljs.highlightBlock(pres[i]);\n        }\n    }\n    highlightCode();\n\u003c/script\u003e\n```\n\n## License\nThe Westwind.Web.MarkdownControl library is an open source product licensed under:\n\n* **[MIT license](http://opensource.org/licenses/MIT)**\n\nAll source code is **\u0026copy; West Wind Technologies**, regardless of changes made to them. Any source code modifications must leave the original copyright code headers intact if present.\n\nThere's no charge to use, integrate or modify the code for this project. You are free to use it in personal, commercial, government and any other type of application and you are free to modify the code for use in your own projects.\n\n### Give back\nIf you find this library useful, consider making a small donation:\n\n\u003ca href=\"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=3RZRUFCWD24R4\" \n    title=\"Find this library useful? Consider making a small donation.\" alt=\"Make Donation\" style=\"text-decoration: none;\"\u003e\n\t\u003cimg src=\"https://weblog.west-wind.com/images/donation.png\" /\u003e\n\u003c/a\u003e\n\n## Acknowledgements\nThis library uses the following excellent components:\n\n* [MarkDig Markdown Parser](https://github.com/lunet-io/markdig)\n\n---\n\n\u003cdiv style=\"margin-top: 30px;font-size: 0.8em;\n            border-top: 1px solid #eee;padding-top: 8px;\"\u003e\n    \u003cimg src=\"https://markdownmonster.west-wind.com/favicon.png\"\n         style=\"height: 20px;float: left; margin-right: 10px;\" height=\"20\" width=\"20\" /\u003e\n    content created and published with \n    \u003ca href=\"https://markdownmonster.west-wind.com\"\n       target=\"top\"\u003eMarkdown Monster\u003c/a\u003e\n\u003c/div\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickstrahl%2Fwestwind.web.markdown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frickstrahl%2Fwestwind.web.markdown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickstrahl%2Fwestwind.web.markdown/lists"}