[{"data":1,"prerenderedAt":608},["ShallowReactive",2],{"markdown-doc:\u002Fen\u002Fguide\u002Fcomparison":3},{"id":4,"title":5,"body":6,"description":598,"extension":75,"keywords":599,"locale":600,"meta":601,"navigation":107,"order":602,"path":603,"section":604,"seo":605,"stem":606,"__hash__":607},"docs\u002Fguide\u002Fcomparison.en.md","Compared with Incremark",{"type":7,"value":8,"toc":577},"minimark",[9,17,24,29,32,35,42,45,49,54,57,60,64,67,70,124,131,138,142,146,149,199,210,214,221,255,269,286,289,349,353,357,360,364,367,370,374,381,384,394,397,401,404,407,411,414,417,426,430,433,436,444,448,451,454,462,466,469,487,491,494,536,554,573],[10,11,12,16],"p",{},[13,14,15],"strong",{},"Incremark was our first streaming Markdown tool."," QuireKit Markdown continues the same goal:\nshow formatted content while an AI response is still arriving.",[10,18,19,20,23],{},"The redesign addresses an easy-to-miss problem: ",[13,21,22],{},"text received later can change how an earlier\nsentence should appear."," The new engine reduces repeated parsing and rendering while allowing\nlater definitions to update earlier text correctly.",[25,26,28],"h2",{"id":27},"watch-a-tree-change","Watch a tree change",[10,30,31],{},"“Middle insert” changes the same source three times: bold text in the second paragraph,\ninline code in the first, then a two-item list between paragraphs. Each edit builds on the previous result.",[10,33,34],{},"Play to follow each fragment into the source and along the highlighted path to an amber affected\nbranch, followed by blue updated nodes. Green branches retain their native objects. Pause, step,\ngo back, or select an insertion and phase. The view has no drag, pan or zoom.",[10,36,37,38,41],{},"The third edit is at a paragraph boundary. Although the final paragraph's literal text is unchanged,\nits native branch is rebuilt: the affected scope depends on syntax and context, not just changed characters.\n“Tail append” and “Late reference” remain available; in the latter, ",[13,39,40],{},"bar"," becomes the earlier link.\nTrees and output come from the real engine. The motion is teaching choreography, not an internal execution log.",[10,43,44],{},"This tree animation also uses our Flowchart library: nodes, edges, moving fragments and tree replacements share one public player.",[46,47],"docs-demo",{"name":48},"algorithms\u002Fplayback",[50,51,53],"h3",{"id":52},"compare-the-earlier-flow","Compare the earlier flow",[10,55,56],{},"Switch between “Earlier Incremark” and “Current algorithm” to follow a new chunk through the system.\nOur existing Flow Editor renderer provides zoom and a larger view.",[46,58],{"name":59},"algorithms\u002Fflow",[25,61,63],{"id":62},"why-redesign-it","Why redesign it",[10,65,66],{},"Earlier Incremark divided a growing response into finished blocks and the part still being written.\nWhen more text arrived, it tried to preserve earlier parse results and reparse only the tail.\nThat reduced repeated work.",[10,68,69],{},"But finishing a paragraph does not always settle its meaning. An AI can write the text first and\nprovide a link destination at the end:",[71,72,77],"pre",{"className":73,"code":74,"language":75,"meta":76,"style":76},"language-md shiki shiki-themes github-light github-light github-dark","更多内容见[文档][api]。\n\n[api]: https:\u002F\u002Fexample.com\u002Fdocs\n","md","",[78,79,80,102,109],"code",{"__ignoreMap":76},[81,82,85,89,93,96,99],"span",{"class":83,"line":84},"line",1,[81,86,88],{"class":87},"sVPnS","更多内容见[",[81,90,92],{"class":91},"snQV0","文档",[81,94,95],{"class":87},"][",[81,97,98],{"class":91},"api",[81,100,101],{"class":87},"]。\n",[81,103,105],{"class":83,"line":104},2,[81,106,108],{"emptyLinePlaceholder":107},true,"\n",[81,110,112,115,117,120],{"class":83,"line":111},3,[81,113,114],{"class":87},"[",[81,116,98],{"class":91},[81,118,119],{"class":87},"]: ",[81,121,123],{"class":122},"svczC","https:\u002F\u002Fexample.com\u002Fdocs\n",[10,125,126,127,130],{},"Until the last line arrives, ",[78,128,129],{},"[文档][api]"," has no destination. Once it arrives, “文档” should become\na link. Footnotes work similarly: a reference can appear long before its explanation.",[10,132,133,134,137],{},"The earlier version handled these cases by recording references and filling in their destinations later.\nThe difficulty is that a later definition can also change ",[13,135,136],{},"which brackets form a link",". Adding a\ndestination to an existing node is then insufficient. Earlier syntax needs another look, and the page\nneeds the corresponding update.",[25,139,141],{"id":140},"two-concrete-problems-in-the-earlier-implementation","Two concrete problems in the earlier implementation",[50,143,145],{"id":144},"defining-the-same-link-twice","Defining the same link twice",[10,147,148],{},"Suppose the paragraph and each destination arrive in order:",[71,150,152],{"className":73,"code":151,"language":75,"meta":76,"style":76},"[文档][api]\n\n[api]: \u002Ffirst\n\n[api]: \u002Fsecond\n",[78,153,154,167,171,182,187],{"__ignoreMap":76},[81,155,156,158,160,162,164],{"class":83,"line":84},[81,157,114],{"class":87},[81,159,92],{"class":91},[81,161,95],{"class":87},[81,163,98],{"class":91},[81,165,166],{"class":87},"]\n",[81,168,169],{"class":83,"line":104},[81,170,108],{"emptyLinePlaceholder":107},[81,172,173,175,177,179],{"class":83,"line":111},[81,174,114],{"class":87},[81,176,98],{"class":91},[81,178,119],{"class":87},[81,180,181],{"class":122},"\u002Ffirst\n",[81,183,185],{"class":83,"line":184},4,[81,186,108],{"emptyLinePlaceholder":107},[81,188,190,192,194,196],{"class":83,"line":189},5,[81,191,114],{"class":87},[81,193,98],{"class":91},[81,195,119],{"class":87},[81,197,198],{"class":122},"\u002Fsecond\n",[10,200,201,202,205,206,209],{},"Markdown uses the first definition of a label, so “文档” should link to ",[78,203,204],{},"\u002Ffirst",".\nThe earlier implementation overwrote the first value when merging definitions, changing the link\nto ",[78,207,208],{},"\u002Fsecond",". The current engine preserves the first definition.",[50,211,213],{"id":212},"linking-the-wrong-word","Linking the wrong word",[10,215,216,217,220],{},"Consider another short example. The first line arrives, followed by the definition for ",[78,218,219],{},"baz",":",[71,222,224],{"className":73,"code":223,"language":75,"meta":76,"style":76},"[foo][bar][baz]\n\n[baz]: \u002Ftarget\n",[78,225,226,240,244],{"__ignoreMap":76},[81,227,228,230,233,235,237],{"class":83,"line":84},[81,229,114],{"class":87},[81,231,232],{"class":91},"foo",[81,234,95],{"class":87},[81,236,40],{"class":91},[81,238,239],{"class":87},"][baz]\n",[81,241,242],{"class":83,"line":104},[81,243,108],{"emptyLinePlaceholder":107},[81,245,246,248,250,252],{"class":83,"line":111},[81,247,114],{"class":87},[81,249,219],{"class":91},[81,251,119],{"class":87},[81,253,254],{"class":122},"\u002Ftarget\n",[10,256,257,258,261,262,265,266,268],{},"The intended reading is literal ",[78,259,260],{},"[foo]",", followed by the link ",[78,263,264],{},"[bar][baz]",". The clickable word is ",[13,267,40],{},".",[10,270,271,272,275,276,279,280,282,283,285],{},"The earlier version had already recognized ",[78,273,274],{},"[foo][bar]"," as one reference and left ",[78,277,278],{},"[baz]"," as another.\nWhen the destination arrived, ",[13,281,219],{}," became clickable. Filling in the address could not correct the\nearlier grouping. The current engine checks grouping against the definitions that actually arrived,\nso ",[13,284,40],{}," becomes the link.",[10,287,288],{},"We ran both earlier engines on these examples again:",[290,291,292,311],"table",{},[293,294,295],"thead",{},[296,297,298,302,305,308],"tr",{},[299,300,301],"th",{},"Case",[299,303,304],{},"Earlier Marked",[299,306,307],{},"Earlier Micromark",[299,309,310],{},"Current QuireKit Markdown",[312,313,314,336],"tbody",{},[296,315,316,323,328,332],{},[317,318,319,320,322],"td",{},"Define ",[78,321,98],{}," twice",[317,324,325,326],{},"Links to ",[78,327,208],{},[317,329,325,330],{},[78,331,208],{},[317,333,325,334],{},[78,335,204],{},[296,337,338,341,344,346],{},[317,339,340],{},"Three adjacent bracket groups",[317,342,343],{},"baz is clickable",[317,345,343],{},[317,347,348],{},"bar is clickable",[25,350,352],{"id":351},"how-the-new-algorithm-handles-a-stream","How the new algorithm handles a stream",[50,354,356],{"id":355},"_1-keep-the-source-that-arrived","1. Keep the source that arrived",[10,358,359],{},"Every append updates the same Markdown source. Stopping preserves the received text without adding\nfences, brackets or HTML closing tags for display. Switching messages starts a new parsing session.",[50,361,363],{"id":362},"_2-let-lezer-identify-reusable-parse-results","2. Let Lezer identify reusable parse results",[10,365,366],{},"Lezer records headings, paragraphs, lists and links in a syntax tree. When text arrives, it uses\nsyntax context to decide which earlier results remain usable and which need parsing again.\nWe use that mechanism for streamed appends.",[10,368,369],{},"For example, starting a paragraph at the end can leave unaffected earlier paragraphs reusable.\nChanges to lists or fences are handled according to their syntax, rather than treating a blank line\nalone as proof that earlier content is finished.",[50,371,373],{"id":372},"_3-let-later-definitions-correct-earlier-references","3. Let later definitions correct earlier references",[10,375,376,377,380],{},"The new engine collects the current link definitions, then checks which paragraphs' reference\ndecisions were affected. ",[78,378,379],{},"[foo][bar][baz]"," needs a new grouping decision; repeated definitions\nkeep the first value.",[10,382,383],{},"It also records labels a paragraph queried, including those not yet defined. When those records\nprovide enough evidence that a new definition did not affect the paragraph, its result remains reusable.",[10,385,386,387,389,390,393],{},"This whiteboard shows the dependencies: when ",[78,388,98],{}," arrives, paragraph B needs another check.\nAn introduction and a paragraph that only queried ",[78,391,392],{},"faq"," can remain reusable when their other inputs match.",[46,395],{"name":396},"algorithms\u002Freferences",[50,398,400],{"id":399},"_4-check-displayed-content-before-reusing-it","4. Check displayed content before reusing it",[10,402,403],{},"Unchanged syntax can still have a different link destination or footnote number. The rendering cache\nchecks those inputs too, along with components and HTML configuration. Matching entries retain their\noutput; affected blocks, or blocks without enough evidence, are generated again.",[10,405,406],{},"As the AI continues writing, reusable earlier content stays in place. When a later definition changes\nits meaning, earlier links and footnotes can still update.",[50,408,410],{"id":409},"who-owns-these-steps","Who owns these steps",[10,412,413],{},"The core owns parsing, reference decisions and cache validation. Vue and React own their components\nand commit lifecycle; the application owns network delivery and optional diagram renderers.",[46,415],{"name":416},"algorithms\u002Flayers",[10,418,419,420,425],{},"All three diagrams retain their native source. You can also integrate these\n",[421,422,424],"a",{"href":423},"\u002Fen\u002Fguide\u002Fdiagrams","flowchart, mind-map and whiteboard renderers"," in your own documentation.",[25,427,429],{"id":428},"watch-a-stream","Watch a stream",[10,431,432],{},"Start the example to watch text arrive before its link and footnote definitions. The same footnote\nis referenced twice, and its body also contains a link. Stop to retain the text received so far.",[46,434],{"name":435},"reading\u002Fstream",[10,437,438,439,443],{},"You can also paste either short example into the ",[421,440,442],{"href":441},"\u002Fen\u002Fplayground","Playground"," to inspect the new engine's output.",[25,445,447],{"id":446},"what-about-speed","What about speed",[10,449,450],{},"Earlier Marked is fast. Switching to Lezer does not make every Markdown input faster to parse.\nThe current optimizations reduce two kinds of repeated work: parsing unaffected text again and\nrebuilding reusable display output.",[10,452,453],{},"An earlier original-demo parse measurement put Lezer\u002FMSFE ahead of the old Micromark and behind the\nold Marked. Those measurements predate the current rendering cache and cannot rank the current version.",[10,455,456,457,461],{},"A large list, table or long paragraph can still be processed as one block. Streaming performance\ndepends on parsing, rendering and browser updates together. See ",[421,458,460],{"href":459},"\u002Fen\u002Fguide\u002Fperformance","performance","\nfor the measurement method.",[25,463,465],{"id":464},"using-it-and-migrating","Using it and migrating",[10,467,468],{},"QuireKit Markdown supports Vue and React with shared parsing rules. Basic usage still takes Markdown\ntext. You can replace links, code blocks and other elements with your components, add custom syntax,\nand explicitly enable HTML.",[10,470,471,472,476,477,481,482,486],{},"The new package does not retain earlier Incremark APIs, so existing plugins need adaptation.\nStart with ",[421,473,475],{"href":474},"\u002Fen\u002Fguide\u002Fgetting-started","Vue"," or ",[421,478,480],{"href":479},"\u002Fen\u002Fguide\u002Freact","React",", then follow\n",[421,483,485],{"href":484},"\u002Fen\u002Fguide\u002Fextensions","custom syntax and nodes"," for extensions. This remains an unreleased preview.\nEarlier Incremark and the current core, Vue and React packages all use MIT.",[25,488,490],{"id":489},"further-implementation-reading","Further implementation reading",[10,492,493],{},"These details are useful when extending the parser or studying the cache:",[495,496,497,508,514,527],"ul",{},[498,499,500,503,504,507],"li",{},[13,501,502],{},"Syntax reuse:"," CodeMirror maps text transactions and ",[78,505,506],{},"TreeFragment",". Our Lezer layer exposes\ntop-level block reuse while preserving native grammar and reuse decisions. Reference handling\nbelongs to the MSFE parser wrapper.",[498,509,510,513],{},[13,511,512],{},"Reference decisions:"," Complete paragraphs record labels actually queried by grammar and whether\nthey exist. Those decisions are reused only when query results match; ranges without complete\nrecords are checked conservatively. Rendering separately checks destination and title changes.",[498,515,516,519,520,523,524,526],{},[13,517,518],{},"Rendering cache:"," Entries check native Tree identity, source range, reference targets, footnote\nnavigation and rendering configuration. Custom nodes can declare additional dependencies with\n",[78,521,522],{},"cacheKey(document)","; without it, output is generated again. See ",[421,525,460],{"href":459},"\nfor conditions and cache limits.",[498,528,529,532,533,268],{},[13,530,531],{},"Frameworks and resources:"," Vue and React have their own components. React accepts candidate\ncaches after commit and starts resources after client commit. Cancellation and release handle\nswitching, unmount and late results; see ",[421,534,535],{"href":479},"React integration",[10,537,538,539,542,543,546,547,553],{},"The two examples were checked on 2026-10-11 against ",[78,540,541],{},"@incremark\u002Fcore"," 1.0.2, commit ",[78,544,545],{},"98f6b95",".\nEarlier results come from each engine's AST and definitions; current results come from React server\nrendering, checked against an independent full GFM parse and\n",[421,548,552],{"href":549,"rel":550},"https:\u002F\u002Fspec.commonmark.org\u002F0.31.2\u002F#links",[551],"nofollow","CommonMark reference rules",".\nThese examples identify specific problems in that version, without extending the findings to later Incremark versions.",[10,555,556,557,562,563,562,568,268],{},"Source: ",[421,558,561],{"href":559,"rel":560},"https:\u002F\u002Fgithub.com\u002Fkingshuaishuai\u002Fincremark\u002Fblob\u002F98f6b95bba58d0c9e4ba1af37a4d52c2f2fae1df\u002Fpackages\u002Fcore\u002Fsrc\u002Fparser\u002FIncremarkParser.ts",[551],"earlier parser session",",\n",[421,564,567],{"href":565,"rel":566},"https:\u002F\u002Fgithub.com\u002Fkingshuaishuai\u002Fincremark\u002Fblob\u002F98f6b95bba58d0c9e4ba1af37a4d52c2f2fae1df\u002Fpackages\u002Fcore\u002Fsrc\u002Fextensions\u002Fmarked-extensions\u002FoptimisticReferenceExtension.ts",[551],"reference recognition",[421,569,572],{"href":570,"rel":571},"https:\u002F\u002Fgithub.com\u002Fkingshuaishuai\u002Fincremark\u002Fblob\u002F98f6b95bba58d0c9e4ba1af37a4d52c2f2fae1df\u002Fpackages\u002Fcore\u002Fsrc\u002Fparser\u002Fmanager\u002FDefinitionManager.ts",[551],"definition merging",[574,575,576],"style",{},"html pre.shiki code .sVPnS, html code.shiki .sVPnS{--shiki-default:#24292E;--shiki-light:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .snQV0, html code.shiki .snQV0{--shiki-default:#032F62;--shiki-default-text-decoration:underline;--shiki-light:#032F62;--shiki-light-text-decoration:underline;--shiki-dark:#DBEDFF;--shiki-dark-text-decoration:underline}html pre.shiki code .svczC, html code.shiki .svczC{--shiki-default:#24292E;--shiki-default-text-decoration:underline;--shiki-light:#24292E;--shiki-light-text-decoration:underline;--shiki-dark:#E1E4E8;--shiki-dark-text-decoration:underline}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":76,"searchDepth":104,"depth":104,"links":578},[579,582,583,587,594,595,596,597],{"id":27,"depth":104,"text":28,"children":580},[581],{"id":52,"depth":111,"text":53},{"id":62,"depth":104,"text":63},{"id":140,"depth":104,"text":141,"children":584},[585,586],{"id":144,"depth":111,"text":145},{"id":212,"depth":111,"text":213},{"id":351,"depth":104,"text":352,"children":588},[589,590,591,592,593],{"id":355,"depth":111,"text":356},{"id":362,"depth":111,"text":363},{"id":372,"depth":111,"text":373},{"id":399,"depth":111,"text":400},{"id":409,"depth":111,"text":410},{"id":428,"depth":104,"text":429},{"id":446,"depth":104,"text":447},{"id":464,"depth":104,"text":465},{"id":489,"depth":104,"text":490},"Why we redesigned Incremark, and how the new engine handles streaming Markdown.",null,"en",{},7,"\u002Fen\u002Fguide\u002Fcomparison","Reference",{"title":5,"description":598},"guide\u002Fcomparison.en","hdjrL_letwZ5twoUQ7i1KSyoHRfkdz_WwGPc_StfyFQ",1793045320730]