11import type { Readable } from 'node:stream'
2- import type { MDCRoot } from './types/tree'
2+ import type { MDCRoot , MDCElement } from './types/tree'
3+ import type { ParseOptions } from './types'
34import MarkdownIt from 'markdown-it'
45import pluginMdc from 'markdown-it-mdc'
56import { parseFrontMatter } from 'remark-mdc'
67import { autoCloseMarkdown } from './auto-close'
78import { convertMarkdownItTokensToMDC } from './utils/parse'
9+ import { applyAutoUnwrap } from './utils/auto-unwrap'
810import { generateToc } from './utils/table-of-contents'
911
1012export interface ParseResult {
@@ -92,7 +94,8 @@ async function streamToString(stream: Readable | ReadableStream<Uint8Array>): Pr
9294/**
9395 * Internal parse function
9496 */
95- function parseContent ( source : string ) : ParseResult {
97+ function parseContent ( source : string , options : ParseOptions = { } ) : ParseResult {
98+ const { autoUnwrap = true } = options
9699 const { content, data } = parseFrontMatter ( source )
97100 // Enable tables, GFM features
98101 const markdownIt = new MarkdownIt ( {
@@ -107,7 +110,17 @@ function parseContent(source: string): ParseResult {
107110 const children = convertMarkdownItTokensToMDC ( tokens )
108111
109112 // Filter out top-level text nodes
110- const filteredChildren = children . filter ( child => child . type !== 'text' )
113+ let filteredChildren = children . filter ( child => child . type !== 'text' )
114+
115+ // Apply auto-unwrap to container components if enabled
116+ if ( autoUnwrap ) {
117+ filteredChildren = filteredChildren . map ( ( child ) => {
118+ if ( child . type === 'element' ) {
119+ return applyAutoUnwrap ( child as MDCElement )
120+ }
121+ return child
122+ } )
123+ }
111124
112125 const body : MDCRoot = {
113126 type : 'root' ,
@@ -122,7 +135,18 @@ function parseContent(source: string): ParseResult {
122135
123136 if ( excerptIndex !== - 1 ) {
124137 const excerptTokens = tokens . slice ( 0 , excerptIndex )
125- const excerptChildren = convertMarkdownItTokensToMDC ( excerptTokens , new Set ( ) )
138+ let excerptChildren = convertMarkdownItTokensToMDC ( excerptTokens as any , new Set ( ) )
139+
140+ // Apply auto-unwrap to excerpt as well
141+ if ( autoUnwrap ) {
142+ excerptChildren = excerptChildren . map ( ( child ) => {
143+ if ( child . type === 'element' ) {
144+ return applyAutoUnwrap ( child as MDCElement )
145+ }
146+ return child
147+ } )
148+ }
149+
126150 excerpt = {
127151 type : 'root' ,
128152 children : excerptChildren . filter ( child => child . type !== 'text' ) ,
@@ -156,6 +180,7 @@ function parseContent(source: string): ParseResult {
156180 * Parse MDC content from a Node.js Readable stream or Web ReadableStream
157181 *
158182 * @param stream - A Node.js Readable stream or Web ReadableStream containing MDC content
183+ * @param options - Parser options
159184 * @returns Promise resolving to the parsed MDC structure
160185 *
161186 * @example
@@ -166,18 +191,22 @@ function parseContent(source: string): ParseResult {
166191 * const stream = createReadStream('content.md')
167192 * const result = await parseStream(stream)
168193 * console.log(result.body)
194+ *
195+ * // Disable auto-unwrap
196+ * const result2 = await parseStream(stream, { autoUnwrap: false })
169197 * ```
170198 */
171- export async function parseStream ( stream : Readable | ReadableStream < Uint8Array > ) : Promise < ParseResult > {
199+ export async function parseStream ( stream : Readable | ReadableStream < Uint8Array > , options ?: ParseOptions ) : Promise < ParseResult > {
172200 const content = await streamToString ( stream )
173- return parseContent ( content )
201+ return parseContent ( content , options )
174202}
175203
176204/**
177205 * Parse MDC content incrementally from a stream,
178206 * yielding results as each chunk is received
179207 *
180208 * @param stream - A Node.js Readable stream or Web ReadableStream containing MDC content
209+ * @param options - Parser options
181210 * @yields IncrementalParseResult for each chunk received
182211 *
183212 * @example
@@ -191,10 +220,16 @@ export async function parseStream(stream: Readable | ReadableStream<Uint8Array>)
191220 * console.log('Current body:', result.body)
192221 * console.log('Complete:', result.isComplete)
193222 * }
223+ *
224+ * // Disable auto-unwrap
225+ * for await (const result of parseStreamIncremental(stream, { autoUnwrap: false })) {
226+ * // ...
227+ * }
194228 * ```
195229 */
196230export async function * parseStreamIncremental (
197231 stream : Readable | ReadableStream < Uint8Array > ,
232+ options ?: ParseOptions ,
198233) : AsyncGenerator < IncrementalParseResult , void , unknown > {
199234 let accumulatedContent = ''
200235 let frontmatterParsed = false
@@ -230,7 +265,7 @@ export async function* parseStreamIncremental(
230265 const closedContent = autoCloseMarkdown ( accumulatedContent )
231266
232267 // Parse the auto-closed content
233- const result = parseContent ( closedContent )
268+ const result = parseContent ( closedContent , options )
234269
235270 yield {
236271 chunk : chunkStr ,
@@ -242,7 +277,7 @@ export async function* parseStreamIncremental(
242277 }
243278
244279 // Final parse with complete content (no auto-close needed, content is complete)
245- const finalResult = parseContent ( accumulatedContent )
280+ const finalResult = parseContent ( accumulatedContent , options )
246281 yield {
247282 chunk : '' ,
248283 body : finalResult . body ,
@@ -263,7 +298,7 @@ export async function* parseStreamIncremental(
263298
264299 if ( done ) {
265300 // Final parse with complete content
266- const finalResult = parseContent ( accumulatedContent )
301+ const finalResult = parseContent ( accumulatedContent , options )
267302 yield {
268303 chunk : '' ,
269304 body : finalResult . body ,
@@ -289,7 +324,7 @@ export async function* parseStreamIncremental(
289324 const closedContent = autoCloseMarkdown ( accumulatedContent )
290325
291326 // Parse the auto-closed content
292- const result = parseContent ( closedContent )
327+ const result = parseContent ( closedContent , options )
293328
294329 yield {
295330 chunk : chunkStr ,
0 commit comments