<?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: king</title>
    <description>The latest articles on DEV Community by king (@kingshuaishuai).</description>
    <link>https://dev.to/kingshuaishuai</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%2F1350493%2F54523e59-952a-4d03-88eb-0caa8b6bb06f.jpeg</url>
      <title>DEV Community: king</title>
      <link>https://dev.to/kingshuaishuai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kingshuaishuai"/>
    <language>en</language>
    <item>
      <title>New Incremark DevTools Release: Built with Svelte, Now with Multi-Parser Support</title>
      <dc:creator>king</dc:creator>
      <pubDate>Sun, 11 Jan 2026 15:20:10 +0000</pubDate>
      <link>https://dev.to/kingshuaishuai/new-incremark-devtools-release-built-with-svelte-now-with-multi-parser-support-39on</link>
      <guid>https://dev.to/kingshuaishuai/new-incremark-devtools-release-built-with-svelte-now-with-multi-parser-support-39on</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/kingshuaishuai/incremark" rel="noopener noreferrer"&gt;Incremark&lt;/a&gt; is a high-performance incremental Markdown parser designed for AI streaming output. We're excited to announce a complete rewrite of Incremark DevTools! The new version is built with Svelte, bringing better performance, internationalization support, and a more polished debugging experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Incremark
&lt;/h2&gt;

&lt;p&gt;Incremark uses incremental parsing technology — only new content is parsed, completed blocks are never reprocessed. The longer the document, the more pronounced the performance advantage — from 4-6x faster on short documents to 16-65x faster on long documents.&lt;/p&gt;

&lt;p&gt;Supports Vue, React, Svelte, and Solid frameworks with full TypeScript definitions and rich customization options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Star us on GitHub ⭐️&lt;/strong&gt;: &lt;a href="https://github.com/kingshuaishuai/incremark" rel="noopener noreferrer"&gt;https://github.com/kingshuaishuai/incremark&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Report Issues 🐛&lt;/strong&gt;: &lt;a href="https://github.com/kingshuaishuai/incremark/issues" rel="noopener noreferrer"&gt;https://github.com/kingshuaishuai/incremark/issues&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's New
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🌐 Internationalization (i18n)
&lt;/h3&gt;

&lt;p&gt;DevTools now supports both Chinese and English interfaces! You can switch languages dynamically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setLocale&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@incremark/devtools&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Switch to Chinese&lt;/span&gt;
&lt;span class="nf"&gt;setLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zh-CN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Switch to English&lt;/span&gt;
&lt;span class="nf"&gt;setLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔌 Multi-Parser Support
&lt;/h3&gt;

&lt;p&gt;Monitor multiple parser instances simultaneously! This is incredibly useful when you have different Markdown parsers in your application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjkoj5qgzyxybl7mse6ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjkoj5qgzyxybl7mse6ls.png" alt=" " width="800" height="994"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🎨 Framework-Agnostic Design
&lt;/h3&gt;

&lt;p&gt;DevTools is now completely framework-agnostic. It works seamlessly with Vue, React, Svelte, Solid, and vanilla JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux3w1ogmfiogrqvnrzfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux3w1ogmfiogrqvnrzfj.png" alt=" " width="800" height="928"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbzo86895b5t3kl7w1v3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbzo86895b5t3kl7w1v3.png" alt=" " width="800" height="979"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4dfzg1czqf853prd9o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4dfzg1czqf853prd9o0.png" alt=" " width="800" height="989"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn13jjlroamqjtozb3i78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn13jjlroamqjtozb3i78.png" alt=" " width="800" height="968"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📊 Enhanced Features
&lt;/h3&gt;

&lt;p&gt;The new DevTools includes four powerful tabs: Overview, Blocks, AST, and Timeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration Guide
&lt;/h2&gt;

&lt;p&gt;The old &lt;code&gt;useDevTools()&lt;/code&gt; hook has been removed. The new API uses &lt;code&gt;createDevTools()&lt;/code&gt; to create instances and &lt;code&gt;mount()&lt;/code&gt;/&lt;code&gt;unmount()&lt;/code&gt; for lifecycle management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Demos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Vue Demo: &lt;a href="https://vue.incremark.com/" rel="noopener noreferrer"&gt;https://vue.incremark.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;React Demo: &lt;a href="https://react.incremark.com/" rel="noopener noreferrer"&gt;https://react.incremark.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Svelte Demo: &lt;a href="https://svelte.incremark.com/" rel="noopener noreferrer"&gt;https://svelte.incremark.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Solid Demo: &lt;a href="https://solid.incremark.com/" rel="noopener noreferrer"&gt;https://solid.incremark.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devtools</category>
      <category>svelte</category>
      <category>opensource</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Incremark Now Supports Solid: One Library for Vue, React, Svelte, and Solid</title>
      <dc:creator>king</dc:creator>
      <pubDate>Sat, 10 Jan 2026 19:08:17 +0000</pubDate>
      <link>https://dev.to/kingshuaishuai/incremark-now-supports-solid-one-library-for-vue-react-svelte-and-solid-n39</link>
      <guid>https://dev.to/kingshuaishuai/incremark-now-supports-solid-one-library-for-vue-react-svelte-and-solid-n39</guid>
      <description>&lt;p&gt;Incremark now supports Solid, completing our coverage of all four major frontend frameworks: Vue, React, Svelte, and Solid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Framework-Agnostic?
&lt;/h2&gt;

&lt;p&gt;Most Markdown rendering libraries are built for specific frameworks. React has react-markdown, Vue has various v-md components. This creates problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Duplicated effort&lt;/strong&gt;: Each framework community independently implements similar features&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inconsistent capabilities&lt;/strong&gt;: Implementation quality varies across frameworks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switching costs&lt;/strong&gt;: Changing frameworks means learning a new API&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Incremark takes a different approach: &lt;strong&gt;core logic is completely decoupled from UI frameworks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@incremark/core&lt;/code&gt; handles all parsing, transformation, and incremental updates, outputting framework-agnostic data structures. Framework packages (&lt;code&gt;@incremark/vue&lt;/code&gt;, &lt;code&gt;@incremark/react&lt;/code&gt;, &lt;code&gt;@incremark/svelte&lt;/code&gt;, &lt;code&gt;@incremark/solid&lt;/code&gt;) simply render this data as framework-specific components.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Core capabilities implemented once, benefiting all four frameworks&lt;/li&gt;
&lt;li&gt;Bug fixes and performance optimizations automatically sync to all frameworks&lt;/li&gt;
&lt;li&gt;Consistent API design, near-zero learning curve when switching frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Package Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────────────────────────────┐
│       @incremark/core         │
│                               │
│  Incremental · Dual Engine ·  │
│        Plugin System          │
└───────────────┬───────────────┘
                │
                ▼
┌───────────────────────────────┐
│  @incremark/vue               │
│  @incremark/react             │
│  @incremark/svelte            │
│  @incremark/solid  ← NEW      │
└───────────────┬───────────────┘
                │
                ▼
┌───────────────────────────────┐
│       @incremark/theme        │
│                               │
│  Styles · Themes · Syntax     │
│        Highlighting           │
└───────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Incremental Parsing
&lt;/h2&gt;

&lt;p&gt;Traditional Markdown renderers have performance issues in streaming scenarios: they re-parse the entire document whenever new content arrives, resulting in O(n²) complexity.&lt;/p&gt;

&lt;p&gt;Incremark only processes new content. Already-parsed blocks are never reprocessed, reducing complexity to O(n).&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage Across All Four Frameworks
&lt;/h2&gt;

&lt;p&gt;The component API is identical across all four frameworks, differing only in syntax:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vue&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IncremarkContent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@incremark/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;IncremarkContent&lt;/span&gt; &lt;span class="na"&gt;:content=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt; &lt;span class="na"&gt;:is-finished=&lt;/span&gt;&lt;span class="s"&gt;"isFinished"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IncremarkContent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@incremark/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IncremarkContent&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;isFinished&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isFinished&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Svelte&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight svelte"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IncremarkContent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@incremark/svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;IncremarkContent&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;isFinished=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isFinished&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solid&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IncremarkContent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@incremark/solid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IncremarkContent&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="nx"&gt;isFinished&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;isFinished&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apart from each framework's reactive syntax (Vue's &lt;code&gt;ref&lt;/code&gt;, React's &lt;code&gt;useState&lt;/code&gt;, Svelte's &lt;code&gt;$state&lt;/code&gt;, Solid's &lt;code&gt;createSignal&lt;/code&gt;), the component usage is completely unified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Demos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://solid.incremark.com/" rel="noopener noreferrer"&gt;Solid Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vue.incremark.com/" rel="noopener noreferrer"&gt;Vue Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.incremark.com/" rel="noopener noreferrer"&gt;React Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://svelte.incremark.com/" rel="noopener noreferrer"&gt;Svelte Demo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/@incremark/core" rel="noopener noreferrer"&gt;@incremark/core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://www.incremark.com" rel="noopener noreferrer"&gt;incremark.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/anthropics/incremark" rel="noopener noreferrer"&gt;github.com/anthropics/incremark&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT License.&lt;/p&gt;

</description>
      <category>incremark</category>
      <category>markdown</category>
      <category>solid</category>
      <category>ai</category>
    </item>
    <item>
      <title>From O(n ) to O(n): Building a Streaming Markdown Renderer for the AI Era</title>
      <dc:creator>king</dc:creator>
      <pubDate>Thu, 08 Jan 2026 03:32:35 +0000</pubDate>
      <link>https://dev.to/kingshuaishuai/from-on2-to-on-building-a-streaming-markdown-renderer-for-the-ai-era-3k0f</link>
      <guid>https://dev.to/kingshuaishuai/from-on2-to-on-building-a-streaming-markdown-renderer-for-the-ai-era-3k0f</guid>
      <description>&lt;h1&gt;
  
  
  From O(n²) to O(n): Building a Streaming Markdown Renderer for the AI Era
&lt;/h1&gt;

&lt;p&gt;If you've built an AI chat application, you've probably noticed something frustrating: &lt;strong&gt;the longer the conversation gets, the slower the rendering becomes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The reason is simple — every time the AI outputs a new token, traditional markdown parsers re-parse the &lt;em&gt;entire&lt;/em&gt; document from scratch. This is a fundamental architectural problem, and it only gets worse as AI outputs get longer.&lt;/p&gt;

&lt;p&gt;We built &lt;strong&gt;Incremark&lt;/strong&gt; to fix this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Truth About AI in 2025
&lt;/h2&gt;

&lt;p&gt;If you've been following AI trends, you know the numbers are getting crazy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2022&lt;/strong&gt;: GPT-3.5 responses? A few hundred words, no big deal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2023&lt;/strong&gt;: GPT-4 cranks it up to 2,000-4,000 words&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2024-2025&lt;/strong&gt;: Reasoning models (o1, DeepSeek R1) are outputting &lt;strong&gt;10,000+ word "thinking processes"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We're moving from 4K token conversations to 32K, even 128K. And here's the thing nobody talks about: &lt;strong&gt;rendering 500 words and rendering 50,000 words of Markdown are completely different engineering problems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most markdown libraries? They were built for blog posts. Not for AI that thinks out loud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Your Markdown Parser is Lying to You
&lt;/h2&gt;

&lt;p&gt;Here's what happens under the hood when you stream AI output through a traditional parser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chunk 1: Parse 100 chars ✓
Chunk 2: Parse 200 chars (100 old + 100 new)
Chunk 3: Parse 300 chars (200 old + 100 new)
...
Chunk 100: Parse 10,000 chars 😰
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Total work: &lt;code&gt;100 + 200 + 300 + ... + 10,000 = 5,050,000&lt;/code&gt; character operations.&lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;O(n²)&lt;/strong&gt;. The cost doesn't just grow — it &lt;em&gt;explodes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For a 20KB AI response, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ant-design-x&lt;/strong&gt;: 1,657 ms parsing time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;markstream-vue&lt;/strong&gt;: 5,755 ms (almost &lt;strong&gt;6 seconds&lt;/strong&gt; of parsing!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And these are popular, well-maintained libraries. The problem isn't bad code — it's the wrong architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Key Insight
&lt;/h2&gt;

&lt;p&gt;Here's the thing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Once a markdown block is "complete", it will never change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think about it. When the AI outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Heading&lt;/span&gt;

This is a paragraph.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that second blank line, the paragraph is &lt;em&gt;done&lt;/em&gt;. Locked in. No matter what comes next — code blocks, lists, more paragraphs — that paragraph will never be touched again.&lt;/p&gt;

&lt;p&gt;So why are we re-parsing it 500 times?&lt;/p&gt;

&lt;h2&gt;
  
  
  How Incremark Actually Works
&lt;/h2&gt;

&lt;p&gt;We built &lt;strong&gt;Incremark&lt;/strong&gt; around this insight. The core algorithm:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Detect stable boundaries&lt;/strong&gt; — blank lines, new headings, fence closings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache completed blocks&lt;/strong&gt; — never touch them again&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only re-parse the pending block&lt;/strong&gt; — the one still receiving input
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chunk 1: Parse 100 chars → cache stable blocks
Chunk 2: Parse only ~100 new chars
Chunk 3: Parse only ~100 new chars
...
Chunk 100: Parse only ~100 new chars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Total work: &lt;code&gt;100 × 100 = 10,000&lt;/code&gt; character operations.&lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;500x less work&lt;/strong&gt;. Each character is parsed at most once. That's O(n).&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete Benchmark Data
&lt;/h2&gt;

&lt;p&gt;We benchmarked &lt;strong&gt;38 real markdown files&lt;/strong&gt; — AI conversations, docs, code analysis reports. Not synthetic test data. Total: 6,484 lines, 128.55 KB.&lt;/p&gt;

&lt;p&gt;Here's the full table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Lines&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Incremark&lt;/th&gt;
&lt;th&gt;Streamdown&lt;/th&gt;
&lt;th&gt;markstream-vue&lt;/th&gt;
&lt;th&gt;ant-design-x&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;test-footnotes-simple.md&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;0.09 KB&lt;/td&gt;
&lt;td&gt;0.3 ms&lt;/td&gt;
&lt;td&gt;0.0 ms&lt;/td&gt;
&lt;td&gt;1.4 ms&lt;/td&gt;
&lt;td&gt;0.2 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;simple-paragraphs.md&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;0.41 KB&lt;/td&gt;
&lt;td&gt;0.9 ms&lt;/td&gt;
&lt;td&gt;0.9 ms&lt;/td&gt;
&lt;td&gt;5.9 ms&lt;/td&gt;
&lt;td&gt;1.0 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;introduction.md&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;1.57 KB&lt;/td&gt;
&lt;td&gt;5.6 ms&lt;/td&gt;
&lt;td&gt;12.6 ms&lt;/td&gt;
&lt;td&gt;75.6 ms&lt;/td&gt;
&lt;td&gt;12.8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;footnotes.md&lt;/td&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;0.94 KB&lt;/td&gt;
&lt;td&gt;1.7 ms&lt;/td&gt;
&lt;td&gt;0.2 ms&lt;/td&gt;
&lt;td&gt;10.6 ms&lt;/td&gt;
&lt;td&gt;1.9 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;concepts.md&lt;/td&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;4.29 KB&lt;/td&gt;
&lt;td&gt;12.0 ms&lt;/td&gt;
&lt;td&gt;50.5 ms&lt;/td&gt;
&lt;td&gt;381.9 ms&lt;/td&gt;
&lt;td&gt;53.6 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;comparison.md&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;td&gt;5.39 KB&lt;/td&gt;
&lt;td&gt;20.5 ms&lt;/td&gt;
&lt;td&gt;74.0 ms&lt;/td&gt;
&lt;td&gt;552.2 ms&lt;/td&gt;
&lt;td&gt;85.2 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;complex-html-examples.md&lt;/td&gt;
&lt;td&gt;147&lt;/td&gt;
&lt;td&gt;3.99 KB&lt;/td&gt;
&lt;td&gt;9.0 ms&lt;/td&gt;
&lt;td&gt;58.8 ms&lt;/td&gt;
&lt;td&gt;279.3 ms&lt;/td&gt;
&lt;td&gt;57.2 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FOOTNOTE_FIX_SUMMARY.md&lt;/td&gt;
&lt;td&gt;236&lt;/td&gt;
&lt;td&gt;3.93 KB&lt;/td&gt;
&lt;td&gt;22.7 ms&lt;/td&gt;
&lt;td&gt;0.5 ms&lt;/td&gt;
&lt;td&gt;535.0 ms&lt;/td&gt;
&lt;td&gt;120.8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OPTIMIZATION_SUMMARY.md&lt;/td&gt;
&lt;td&gt;391&lt;/td&gt;
&lt;td&gt;6.24 KB&lt;/td&gt;
&lt;td&gt;19.1 ms&lt;/td&gt;
&lt;td&gt;208.4 ms&lt;/td&gt;
&lt;td&gt;980.6 ms&lt;/td&gt;
&lt;td&gt;217.8 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BLOCK_TRANSFORMER_ANALYSIS.md&lt;/td&gt;
&lt;td&gt;489&lt;/td&gt;
&lt;td&gt;9.24 KB&lt;/td&gt;
&lt;td&gt;75.7 ms&lt;/td&gt;
&lt;td&gt;574.3 ms&lt;/td&gt;
&lt;td&gt;1984.1 ms&lt;/td&gt;
&lt;td&gt;619.9 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;test-md-01.md&lt;/td&gt;
&lt;td&gt;916&lt;/td&gt;
&lt;td&gt;17.67 KB&lt;/td&gt;
&lt;td&gt;87.7 ms&lt;/td&gt;
&lt;td&gt;1441.1 ms&lt;/td&gt;
&lt;td&gt;5754.7 ms&lt;/td&gt;
&lt;td&gt;1656.9 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total (38 files)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6484&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;128.55 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;519.4 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3190.3 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;14683.9 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3728.6 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Being Honest: Where We're Slower
&lt;/h3&gt;

&lt;p&gt;You'll notice something weird in the data. For &lt;code&gt;footnotes.md&lt;/code&gt; and &lt;code&gt;FOOTNOTE_FIX_SUMMARY.md&lt;/code&gt;, Streamdown appears much faster:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Incremark&lt;/th&gt;
&lt;th&gt;Streamdown&lt;/th&gt;
&lt;th&gt;Why?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;footnotes.md&lt;/td&gt;
&lt;td&gt;1.7 ms&lt;/td&gt;
&lt;td&gt;0.2 ms&lt;/td&gt;
&lt;td&gt;Streamdown doesn't support footnotes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FOOTNOTE_FIX_SUMMARY.md&lt;/td&gt;
&lt;td&gt;22.7 ms&lt;/td&gt;
&lt;td&gt;0.5 ms&lt;/td&gt;
&lt;td&gt;Same — it just skips them&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;This isn't a performance issue — it's a feature difference.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When Streamdown encounters &lt;code&gt;[^1]&lt;/code&gt; footnote syntax, it simply ignores it. Incremark fully implements footnotes — and we had to solve a tricky streaming-specific problem:&lt;/p&gt;

&lt;p&gt;In streaming scenarios, &lt;strong&gt;references often arrive before definitions&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chunk 1: "See footnote[^1] for details..."  // reference arrives first
Chunk 2: "More content..."
Chunk 3: "[^1]: This is the definition"     // definition arrives later
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Traditional parsers assume you have the complete document. We built "optimistic references" that gracefully handle incomplete links/images during streaming, then resolve them when definitions arrive.&lt;/p&gt;

&lt;p&gt;We chose to fully implement footnotes, math blocks (&lt;code&gt;$...$&lt;/code&gt;), and custom containers (&lt;code&gt;:::tip&lt;/code&gt;) because that's what real AI content needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where We Actually Shine
&lt;/h3&gt;

&lt;p&gt;Excluding footnote files, look at standard markdown performance:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Lines&lt;/th&gt;
&lt;th&gt;Incremark&lt;/th&gt;
&lt;th&gt;Streamdown&lt;/th&gt;
&lt;th&gt;Advantage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;concepts.md&lt;/td&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;12.0 ms&lt;/td&gt;
&lt;td&gt;50.5 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.2x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;comparison.md&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;td&gt;20.5 ms&lt;/td&gt;
&lt;td&gt;74.0 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.6x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;complex-html-examples.md&lt;/td&gt;
&lt;td&gt;147&lt;/td&gt;
&lt;td&gt;9.0 ms&lt;/td&gt;
&lt;td&gt;58.8 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6.6x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OPTIMIZATION_SUMMARY.md&lt;/td&gt;
&lt;td&gt;391&lt;/td&gt;
&lt;td&gt;19.1 ms&lt;/td&gt;
&lt;td&gt;208.4 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10.9x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;test-md-01.md&lt;/td&gt;
&lt;td&gt;916&lt;/td&gt;
&lt;td&gt;87.7 ms&lt;/td&gt;
&lt;td&gt;1441.1 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;16.4x&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The pattern is clear: the larger the document, the bigger our advantage.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the largest file (17.67 KB):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Incremark&lt;/strong&gt;: 88 ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ant-design-x&lt;/strong&gt;: 1,657 ms (18.9x slower)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;markstream-vue&lt;/strong&gt;: 5,755 ms (65.6x slower)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Such a Huge Gap?
&lt;/h3&gt;

&lt;p&gt;This is O(n) vs O(n²) in action.&lt;/p&gt;

&lt;p&gt;Traditional parsers re-parse the entire document on every chunk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chunk 1: Parse 100 chars
Chunk 2: Parse 200 chars (100 old + 100 new)
Chunk 3: Parse 300 chars (200 old + 100 new)
...
Chunk 100: Parse 10,000 chars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Total work: &lt;code&gt;100 + 200 + ... + 10,000 = 5,050,000&lt;/code&gt; character operations.&lt;/p&gt;

&lt;p&gt;Incremark only processes new content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chunk 1: Parse 100 chars → cache stable blocks
Chunk 2: Parse only ~100 new chars
Chunk 3: Parse only ~100 new chars
...
Chunk 100: Parse only ~100 new chars
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Total work: &lt;code&gt;100 × 100 = 10,000&lt;/code&gt; character operations.&lt;/p&gt;

&lt;p&gt;That's a &lt;strong&gt;500x difference&lt;/strong&gt;. And it only gets worse as documents grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use Incremark
&lt;/h3&gt;

&lt;p&gt;✅ &lt;strong&gt;Use Incremark for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI chat with streaming output (Claude, ChatGPT, etc.)&lt;/li&gt;
&lt;li&gt;Long-form AI content (reasoning models, code generation)&lt;/li&gt;
&lt;li&gt;Real-time markdown editors&lt;/li&gt;
&lt;li&gt;Content requiring footnotes, math, or custom containers&lt;/li&gt;
&lt;li&gt;100K+ token conversations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Consider alternatives for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One-time static markdown rendering (just use marked directly)&lt;/li&gt;
&lt;li&gt;Very small files (&amp;lt;500 characters) — the overhead isn't worth it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Two Engines, One Goal
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Marked or Micromark?&lt;/strong&gt; Both have tradeoffs.&lt;/p&gt;

&lt;p&gt;Marked is blazing fast but lacks advanced features. Micromark is spec-perfect but heavier.&lt;/p&gt;

&lt;p&gt;Our answer: &lt;strong&gt;support both.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Engine&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Marked&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;⚡⚡⚡⚡⚡&lt;/td&gt;
&lt;td&gt;Real-time streaming, AI chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Micromark&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡⚡⚡&lt;/td&gt;
&lt;td&gt;Complex docs, strict CommonMark&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We extended Marked with custom tokenizers for footnotes, math, and containers. If you hit edge cases Marked can't handle, switch to Micromark with one config change.&lt;/p&gt;

&lt;p&gt;Both engines produce identical &lt;strong&gt;mdast&lt;/strong&gt; output. Your rendering code doesn't care which one is running.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Typewriter Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;You know that smooth "typing" effect ChatGPT has? Most implementations do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;displayText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fullText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This breaks markdown constantly. You get half-rendered &lt;code&gt;**bold**&lt;/code&gt; tags, flickering code blocks, syntax that looks drunk.&lt;/p&gt;

&lt;p&gt;We moved the animation to the &lt;strong&gt;AST level&lt;/strong&gt;. Our &lt;code&gt;BlockTransformer&lt;/code&gt; knows the structure — it animates &lt;em&gt;within&lt;/em&gt; nodes, never across them. Result: buttery smooth typing that respects markdown semantics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @incremark/vue  &lt;span class="c"&gt;# or react, or svelte&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IncremarkContent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@incremark/vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isFinished&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;isFinished&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;IncremarkContent&lt;/span&gt; 
    &lt;span class="na"&gt;:content=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt; 
    &lt;span class="na"&gt;:is-finished=&lt;/span&gt;&lt;span class="s"&gt;"isFinished"&lt;/span&gt;
    &lt;span class="na"&gt;:incremark-options=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ gfm: true, math: true }"
  /&amp;gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We support &lt;strong&gt;Vue 3&lt;/strong&gt;, &lt;strong&gt;React 18&lt;/strong&gt;, and &lt;strong&gt;Svelte 5&lt;/strong&gt; with identical APIs. One core, three frameworks, zero behavior differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;This is version 0.3.0. We're just getting started.&lt;/p&gt;

&lt;p&gt;The AI world is moving toward longer outputs, more complex reasoning traces, and richer formatting. Traditional parsers can't keep up — their O(n²) architecture guarantees it.&lt;/p&gt;

&lt;p&gt;We built Incremark because we needed it. Hopefully you find it useful too.&lt;/p&gt;




&lt;p&gt;📚 &lt;strong&gt;Docs&lt;/strong&gt;: &lt;a href="https://www.incremark.com/" rel="noopener noreferrer"&gt;incremark.com&lt;/a&gt;&lt;br&gt;
💻 &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/kingshuaishuai/incremark" rel="noopener noreferrer"&gt;kingshuaishuai/incremark&lt;/a&gt;&lt;br&gt;
🎮 &lt;strong&gt;Live Demos&lt;/strong&gt;: &lt;a href="https://incremark-vue.vercel.app/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt; | &lt;a href="https://incremark-react.vercel.app/" rel="noopener noreferrer"&gt;React&lt;/a&gt; | &lt;a href="https://incremark-svelte.vercel.app/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this saved you debugging time, a ⭐️ on GitHub would mean a lot. Questions? Open an issue or drop a comment below.&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>performance</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Eliminate Redundant Markdown Parsing: Typically 2-10x Faster AI Streaming</title>
      <dc:creator>king</dc:creator>
      <pubDate>Tue, 16 Dec 2025 03:44:43 +0000</pubDate>
      <link>https://dev.to/kingshuaishuai/eliminate-redundant-markdown-parsing-typically-2-10x-faster-ai-streaming-4k94</link>
      <guid>https://dev.to/kingshuaishuai/eliminate-redundant-markdown-parsing-typically-2-10x-faster-ai-streaming-4k94</guid>
      <description>&lt;p&gt;Yesterday, I released &lt;a href="https://incremark-docs.vercel.app/" rel="noopener noreferrer"&gt;incremark&lt;/a&gt;, a project I developed over the weekend. The real-world performance exceeded all expectations—&lt;strong&gt;typically delivering 2-10x speed improvements for AI streaming scenarios, with even greater gains for longer documents&lt;/strong&gt;. While initially intended as an internal tool for my product, I realized that open-sourcing it could be a great direction to take.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every time an AI streams a new chunk of text, traditional markdown parsers re-parse the &lt;strong&gt;entire document from scratch&lt;/strong&gt;—wasting CPU cycles on content that's already been rendered. Incremark solves this by parsing only what's new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmark Results: See It to Believe It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Short Markdown Document:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoswjb93bh4p84dsju0x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoswjb93bh4p84dsju0x.png" alt=" " width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Longer Markdown Document:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadvw3drd1n03fnkt1mc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadvw3drd1n03fnkt1mc6.png" alt=" " width="800" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The performance improvement multiplier may vary between benchmark runs due to the chunking strategy. The demo page uses random chunk lengths: &lt;code&gt;const chunks = content.match(/[\s\S]{1,20}/g) || []&lt;/code&gt;. This chunking affects stable block generation and better simulates real-world scenarios where a chunk may contain content from the previous or next chunk. Regardless of how the content is chunked, performance improvements are guaranteed. The demo website does not use any artificial chunking strategies to inflate results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Live Demos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vue Demo: &lt;a href="https://incremark-vue.vercel.app/" rel="noopener noreferrer"&gt;https://incremark-vue.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;React Demo: &lt;a href="https://incremark-react.vercel.app/" rel="noopener noreferrer"&gt;https://incremark-react.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Documentation: &lt;a href="https://incremark-docs.vercel.app/" rel="noopener noreferrer"&gt;https://incremark-docs.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For extremely long markdown documents, the performance gains are even more dramatic. &lt;strong&gt;A 20KB markdown benchmark achieves an incredible 46x speed improvement&lt;/strong&gt;. The longer your content, the more dramatic the speedup—there's no theoretical upper limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Advantages
&lt;/h2&gt;

&lt;p&gt;⚡ &lt;strong&gt;Typically 2-10x faster&lt;/strong&gt; for AI streaming scenarios&lt;br&gt;&lt;br&gt;
🚀 &lt;strong&gt;Even greater speedup&lt;/strong&gt; for longer documents (up to 46x tested)&lt;br&gt;&lt;br&gt;
🎯 &lt;strong&gt;Zero redundant parsing&lt;/strong&gt; - each character is parsed only once&lt;br&gt;&lt;br&gt;
✨ &lt;strong&gt;Perfect for AI streaming&lt;/strong&gt; - optimized for incremental updates&lt;br&gt;&lt;br&gt;
💪 &lt;strong&gt;Works with regular markdown too&lt;/strong&gt; - not just for AI use cases&lt;br&gt;&lt;br&gt;
🔧 &lt;strong&gt;Framework support&lt;/strong&gt; - React and Vue components included&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Is It So Fast?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Problem with Traditional Parsers
&lt;/h3&gt;

&lt;p&gt;Anyone who has built an AI chat application knows that AI streaming output delivers content in small chunks to the frontend. After receiving each chunk, the entire markdown string must be fed to a markdown parser (whether it's remark, marked.js, or markdown-it). These parsers re-parse the entire markdown document every time, even the parts that have already been rendered and are stable. This creates significant performance waste.&lt;/p&gt;

&lt;p&gt;Tools like vue-stream-markdown have made efforts at the rendering layer by rendering stable tokens as stable components and only updating unstable components, achieving smooth streaming output in the UI layer.&lt;/p&gt;

&lt;p&gt;However, this still doesn't solve the fundamental performance issue: &lt;strong&gt;repeated parsing of markdown text&lt;/strong&gt;. This is the real CPU performance monster. The longer the output document, the higher the performance waste.&lt;/p&gt;
&lt;h3&gt;
  
  
  Incremark's Core Performance Optimization
&lt;/h3&gt;

&lt;p&gt;Beyond achieving smooth component reuse and updates at the UI rendering layer, incremark's key innovation is in &lt;strong&gt;markdown parsing&lt;/strong&gt;: &lt;strong&gt;it only parses unstable markdown blocks and never re-parses stable ones&lt;/strong&gt;. This reduces parsing complexity from &lt;strong&gt;O(n²) to O(n)&lt;/strong&gt;. In theory, the longer the output, the greater the performance improvement.&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Incremental Parsing: From O(n²) to O(n)
&lt;/h4&gt;

&lt;p&gt;Traditional parsers re-parse the entire document every time, causing parsing work to grow quadratically. Incremark's &lt;code&gt;IncremarkParser&lt;/code&gt; class uses an incremental parsing strategy (see &lt;code&gt;IncremarkParser.ts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Design Philosophy:&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Maintain a text buffer to receive streaming input&lt;/span&gt;
&lt;span class="c1"&gt;// 2. Identify "stable boundaries" and mark completed blocks as 'completed'&lt;/span&gt;
&lt;span class="c1"&gt;// 3. For blocks currently being received, re-parse only that block's content&lt;/span&gt;
&lt;span class="c1"&gt;// 4. Complex nested nodes are treated as a whole until confirmed complete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Intelligent Boundary Detection
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;findStableBoundary()&lt;/code&gt; method in the &lt;code&gt;append&lt;/code&gt; function is a key optimization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;IncrementalUpdate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateLines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stableBoundary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contextAtLine&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findStableBoundary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stableBoundary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pendingStartLine&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;stableBoundary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Only parse newly completed blocks, never re-parse already completed content&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stableText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pendingStartLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stableBoundary&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stableText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. State Management to Avoid Redundant Computation
&lt;/h4&gt;

&lt;p&gt;The parser maintains several key states to eliminate duplicate work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;buffer&lt;/code&gt;: Accumulated unparsed content&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;completedBlocks&lt;/code&gt;: Array of completed blocks that are never re-parsed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lineOffsets&lt;/code&gt;: Line offset prefix sums, supporting O(1) line position calculations&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;context&lt;/code&gt;: Tracks nesting state of code blocks, lists, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Incremental Line Update Optimization
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;updateLines()&lt;/code&gt; method only processes new content, avoiding full split operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;updateLines&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Find the last incomplete line (which may be continued by a new chunk)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastLineStart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lineOffsets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prevLineCount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;textFromLastLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastLineStart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Re-split only the last line and subsequent content&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newLines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;textFromLastLine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// Only update the changed portions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Comparison
&lt;/h2&gt;

&lt;p&gt;This design delivers exceptional results in real-world testing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Document Size&lt;/th&gt;
&lt;th&gt;Traditional Parser (chars)&lt;/th&gt;
&lt;th&gt;Incremark (chars)&lt;/th&gt;
&lt;th&gt;Reduction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1KB&lt;/td&gt;
&lt;td&gt;1,010,000&lt;/td&gt;
&lt;td&gt;20,000&lt;/td&gt;
&lt;td&gt;98%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5KB&lt;/td&gt;
&lt;td&gt;25,050,000&lt;/td&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;99.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20KB&lt;/td&gt;
&lt;td&gt;400,200,000&lt;/td&gt;
&lt;td&gt;400,000&lt;/td&gt;
&lt;td&gt;99.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Key Invariant
&lt;/h2&gt;

&lt;p&gt;Incremark's performance advantage stems from a key invariant: &lt;strong&gt;Once a block is marked as completed, it is never re-parsed&lt;/strong&gt;. This ensures each character is parsed at most once, achieving O(n) time complexity.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Get Started Now
&lt;/h2&gt;

&lt;p&gt;Stop wasting CPU cycles on redundant parsing. Try incremark today:&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @incremark/core
&lt;span class="c"&gt;# For React&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @incremark/react
&lt;span class="c"&gt;# For Vue&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @incremark/vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📚 &lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="https://incremark-docs.vercel.app/" rel="noopener noreferrer"&gt;https://incremark-docs.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎮 &lt;strong&gt;Live Demo (Vue)&lt;/strong&gt;: &lt;a href="https://incremark-vue.vercel.app/" rel="noopener noreferrer"&gt;https://incremark-vue.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎮 &lt;strong&gt;Live Demo (React)&lt;/strong&gt;: &lt;a href="https://incremark-react.vercel.app/" rel="noopener noreferrer"&gt;https://incremark-react.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/kingshuaishuai/incremark" rel="noopener noreferrer"&gt;https://github.com/kingshuaishuai/incremark&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🤖 AI chat applications with streaming responses&lt;/li&gt;
&lt;li&gt;✍️ Live markdown editors&lt;/li&gt;
&lt;li&gt;📝 Real-time collaborative documents&lt;/li&gt;
&lt;li&gt;📊 Streaming data dashboards with markdown content&lt;/li&gt;
&lt;li&gt;🎓 Interactive learning platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Whether you're building an AI interface or just want faster markdown rendering, incremark delivers the performance you need.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Try It Out &amp;amp; Show Your Support
&lt;/h2&gt;

&lt;p&gt;I'd love for you to &lt;strong&gt;try incremark in your projects&lt;/strong&gt; and see the performance difference for yourself! The live demos are the best way to experience the speed improvements in action.&lt;/p&gt;

&lt;p&gt;If you find incremark useful, please consider &lt;strong&gt;giving it a ⭐ star on GitHub&lt;/strong&gt;—it really helps the project gain visibility and motivates me to keep improving it. Your feedback, issues, and contributions are also highly welcome!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;Star on GitHub&lt;/strong&gt;: &lt;a href="https://github.com/kingshuaishuai/incremark" rel="noopener noreferrer"&gt;https://github.com/kingshuaishuai/incremark&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💡 &lt;strong&gt;Report Issues or Ideas&lt;/strong&gt;: &lt;a href="https://github.com/kingshuaishuai/incremark/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🤝 &lt;strong&gt;Contribute&lt;/strong&gt;: Pull requests are welcome!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for your interest in incremark! Let's make markdown rendering faster together. 🚀&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tooling</category>
      <category>performance</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
