<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: IgorKha</title>
    <description>The latest articles on DEV Community by IgorKha (@igorkha).</description>
    <link>https://dev.to/igorkha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1095593%2F0a5bcf02-7768-4711-9c1b-62bcb684e35a.png</url>
      <title>DEV Community: IgorKha</title>
      <link>https://dev.to/igorkha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igorkha"/>
    <language>en</language>
    <item>
      <title>Building a Markdown editor (Markflow)</title>
      <dc:creator>IgorKha</dc:creator>
      <pubDate>Fri, 24 Apr 2026 08:16:35 +0000</pubDate>
      <link>https://dev.to/igorkha/building-a-markdown-editor-markflow-2oam</link>
      <guid>https://dev.to/igorkha/building-a-markdown-editor-markflow-2oam</guid>
      <description>&lt;p&gt;I’ve been working with Markdown editors both as a user. At some point I wanted to better understand how they actually behave under the hood, especially when documents get more complex (code blocks, math, diagrams, etc.).&lt;/p&gt;

&lt;p&gt;As a small exploration, I built a minimal editor to experiment with these ideas:&lt;br&gt;
&lt;a href="https://github.com/IgorKha/markflow" rel="noopener noreferrer"&gt;https://github.com/IgorKha/markflow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can try it here:&lt;br&gt;
&lt;a href="https://igorkha.github.io/markflow/" rel="noopener noreferrer"&gt;https://igorkha.github.io/markflow/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post is not an announcement, but a summary of a few implementation decisions that might be useful if you’re building something similar.&lt;/p&gt;




&lt;h2&gt;
  
  
  Starting point
&lt;/h2&gt;

&lt;p&gt;The initial goal was simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep Markdown as the source of truth&lt;/li&gt;
&lt;li&gt;support common extensions (code, math, diagrams)&lt;/li&gt;
&lt;li&gt;avoid introducing a separate document format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From there, most of the work ended up around how editing is handled, not rendering.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using Monaco as the editor layer
&lt;/h2&gt;

&lt;p&gt;The editor is built on top of Monaco.&lt;/p&gt;

&lt;p&gt;This gives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a mature text editing model&lt;/li&gt;
&lt;li&gt;good performance characteristics&lt;/li&gt;
&lt;li&gt;predictable behavior for selections, undo/redo, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the same time, Monaco operates on plain text, while Markdown has an implicit structure. Bridging that gap becomes the central problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Working with Markdown as a structure
&lt;/h2&gt;

&lt;p&gt;Instead of treating Markdown purely as a string, the implementation keeps track of its structure (via parsing into an AST).&lt;/p&gt;

&lt;p&gt;This allows reasoning in terms of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blocks (paragraphs, headings, lists)&lt;/li&gt;
&lt;li&gt;fenced regions (code, math, diagrams)&lt;/li&gt;
&lt;li&gt;document hierarchy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even partial structural awareness helps avoid some classes of issues when editing mixed content.&lt;/p&gt;




&lt;h2&gt;
  
  
  Synchronizing structure and editor state
&lt;/h2&gt;

&lt;p&gt;One of the core pieces is keeping two representations in sync:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the text inside Monaco&lt;/li&gt;
&lt;li&gt;the parsed Markdown structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This synchronization is used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detect which block the cursor is currently in&lt;/li&gt;
&lt;li&gt;apply transformations without breaking surrounding content&lt;/li&gt;
&lt;li&gt;keep rendering consistent with the editor state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This part is still evolving, but it defines most of the internal complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rendering pipeline
&lt;/h2&gt;

&lt;p&gt;Rendering is based on standard tools from the Markdown ecosystem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;syntax highlighting via &lt;code&gt;highlight.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;math rendering via &lt;code&gt;KaTeX&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;diagrams via &lt;code&gt;Mermaid&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are applied on top of the parsed Markdown rather than directly on raw text, which keeps responsibilities separated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;parsing → structure&lt;/li&gt;
&lt;li&gt;rendering → visual output&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Mobile behavior
&lt;/h2&gt;

&lt;p&gt;The editor is designed to work in a browser without assuming a desktop environment.&lt;/p&gt;

&lt;p&gt;Some adjustments were made so that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout adapts to smaller screens&lt;/li&gt;
&lt;li&gt;scrolling and input remain usable&lt;/li&gt;
&lt;li&gt;documents can be viewed and edited on mobile devices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a separate mobile version — just the same editor adapted to different screen sizes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sharing without a backend
&lt;/h2&gt;

&lt;p&gt;There is no backend in this project.&lt;/p&gt;

&lt;p&gt;To make sharing possible, the document state can be encoded into a URL. Opening that link reconstructs the document in the editor.&lt;/p&gt;

&lt;p&gt;This approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;does not require storage&lt;/li&gt;
&lt;li&gt;does not persist data server-side&lt;/li&gt;
&lt;li&gt;works for quick sharing or examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s intentionally simple and limited by URL size, but sufficient for lightweight use cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;This project is mainly a technical exploration of how Markdown editing can be structured internally while still using a standard text editor as a base.&lt;/p&gt;

&lt;p&gt;If you’re working on something similar, feedback or discussion would be useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/IgorKha/markflow" rel="noopener noreferrer"&gt;https://github.com/IgorKha/markflow&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Demo: &lt;a href="https://igorkha.github.io/markflow/" rel="noopener noreferrer"&gt;https://igorkha.github.io/markflow/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>markdown</category>
      <category>converter</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
