@@ -118,7 +118,7 @@ export class MarkdownCommand extends MarkdownBase {
118118 }
119119
120120 if ( this . help . length > 0 ) {
121- lines . push ( `## Description for " ${ this . commandName } " ` ) ;
121+ lines . push ( `## Description for ${ this . commandName } ` ) ;
122122 lines . push ( '' ) ;
123123 for ( const paragraph of convertHyphenListsToMarkdown (
124124 this . help . map ( ( p ) => applyCodeFormatting ( escapeAngleBrackets ( p ) ) )
@@ -129,7 +129,7 @@ export class MarkdownCommand extends MarkdownBase {
129129 }
130130
131131 if ( this . aliases . length > 0 ) {
132- lines . push ( `## Aliases for " ${ this . commandName } " ` ) ;
132+ lines . push ( `## Aliases for ${ this . commandName } ` ) ;
133133 lines . push ( '' ) ;
134134 for ( const alias of this . aliases ) {
135135 lines . push ( `\`${ alias } \`` ) ;
@@ -152,7 +152,7 @@ export class MarkdownCommand extends MarkdownBase {
152152 }
153153
154154 if ( this . examples . length > 0 ) {
155- lines . push ( `## Examples for " ${ this . commandName } " ` ) ;
155+ lines . push ( `## Examples for ${ this . commandName } ` ) ;
156156 lines . push ( '' ) ;
157157 for ( const example of this . examples ) {
158158 if ( example . description ) {
@@ -177,8 +177,10 @@ function escapeAngleBrackets(text: string): string {
177177}
178178
179179function applyCodeFormatting ( text : string ) : string {
180+ // First, wrap JSON-like structures (must run before other code formatting to avoid double-wrapping)
181+ let result = wrapJsonInCode ( text ) ;
180182 // Wrap --flag-name tokens (not already in backticks)
181- let result = text . replace ( / (?< ! ` ) - - ( [ \w - ] + ) (? ! ` ) / g, '`--$1`' ) ;
183+ result = result . replace ( / (?< ! ` ) - - ( [ \w - ] + ) (? ! ` ) / g, '`--$1`' ) ;
182184 // Wrap glob patterns like *.cls, *.trigger (not already in backticks)
183185 result = result . replace ( / (?< ! ` ) \* ( \. \w + ) (? ! ` ) / g, '`*$1`' ) ;
184186 // Wrap filenames/extensions with known doc-related extensions (not already in backticks)
@@ -192,18 +194,103 @@ function applyCodeFormatting(text: string): string {
192194 return result ;
193195}
194196
197+ function wrapJsonInCode ( text : string ) : string {
198+ // Strategy: Look for JSON-like patterns and validate them before wrapping
199+ // Match objects like {"key": "value"} or {"key": 123, "key2": true}
200+ // Match arrays like ["value1", "value2"] or [{"key": "value"}]
201+
202+ let result = text ;
203+ const matches : Array < { start : number ; end : number ; content : string } > = [ ] ;
204+
205+ // Find potential JSON objects and arrays
206+ let i = 0 ;
207+ while ( i < text . length ) {
208+ if ( text [ i ] === '{' || text [ i ] === '[' ) {
209+ const openChar = text [ i ] ;
210+ const closeChar = openChar === '{' ? '}' : ']' ;
211+ let depth = 1 ;
212+ let j = i + 1 ;
213+ let inString = false ;
214+ let escape = false ;
215+
216+ // Find matching closing bracket
217+ while ( j < text . length && depth > 0 ) {
218+ if ( escape ) {
219+ escape = false ;
220+ j ++ ;
221+ continue ;
222+ }
223+
224+ if ( text [ j ] === '\\' ) {
225+ escape = true ;
226+ j ++ ;
227+ continue ;
228+ }
229+
230+ if ( text [ j ] === '"' ) {
231+ inString = ! inString ;
232+ } else if ( ! inString ) {
233+ if ( text [ j ] === openChar ) {
234+ depth ++ ;
235+ } else if ( text [ j ] === closeChar ) {
236+ depth -- ;
237+ }
238+ }
239+ j ++ ;
240+ }
241+
242+ if ( depth === 0 ) {
243+ const content = text . substring ( i , j ) ;
244+ // Check if this looks like JSON: must have quotes around keys and colons
245+ if ( looksLikeJson ( content ) ) {
246+ matches . push ( { start : i , end : j , content } ) ;
247+ }
248+ i = j ;
249+ } else {
250+ i ++ ;
251+ }
252+ } else {
253+ i ++ ;
254+ }
255+ }
256+
257+ // Apply wrapping in reverse order to preserve indices
258+ for ( let k = matches . length - 1 ; k >= 0 ; k -- ) {
259+ const { start, end, content } = matches [ k ] ;
260+ // Check if already in backticks
261+ const before = text . substring ( Math . max ( 0 , start - 1 ) , start ) ;
262+ const after = text . substring ( end , Math . min ( text . length , end + 1 ) ) ;
263+ if ( before !== '`' && after !== '`' ) {
264+ result = result . substring ( 0 , start ) + `\`${ content } \`` + result . substring ( end ) ;
265+ }
266+ }
267+
268+ return result ;
269+ }
270+
271+ function looksLikeJson ( text : string ) : boolean {
272+ // Must contain at least one quoted key-value pair with colon, or be an array with quoted strings
273+ const hasKeyValue = / " [ ^ " ] + " \s * : \s * / . test ( text ) ;
274+ const isArray = text . trim ( ) . startsWith ( '[' ) && text . trim ( ) . endsWith ( ']' ) ;
275+ const hasQuotedString = / " [ ^ " ] + " \s * / . test ( text ) ;
276+
277+ return hasKeyValue || ( isArray && hasQuotedString ) ;
278+ }
279+
195280function convertHyphenListsToMarkdown ( paragraphs : string [ ] ) : string [ ] {
196281 const result : string [ ] = [ ] ;
197282 let i = 0 ;
198283 while ( i < paragraphs . length ) {
199- if ( paragraphs [ i ] . startsWith ( '- ' ) ) {
200- // Collect consecutive list items and join with <br> for table cell rendering
284+ if ( paragraphs [ i ] . startsWith ( '- ' ) || paragraphs [ i ] . startsWith ( '* ' ) ) {
285+ // Collect consecutive list items and render as HTML bullet list
201286 const items : string [ ] = [ ] ;
202- while ( i < paragraphs . length && paragraphs [ i ] . startsWith ( '- ' ) ) {
203- items . push ( paragraphs [ i ] ) ;
287+ while ( i < paragraphs . length && ( paragraphs [ i ] . startsWith ( '- ' ) || paragraphs [ i ] . startsWith ( '* ' ) ) ) {
288+ // Remove the leading "- " or "* " and wrap in <li>
289+ items . push ( `<li>${ paragraphs [ i ] . substring ( 2 ) } </li>` ) ;
204290 i ++ ;
205291 }
206- result . push ( items . join ( '<br>' ) ) ;
292+ // Wrap all items in <ul> tags
293+ result . push ( `<ul>${ items . join ( '' ) } </ul>` ) ;
207294 } else {
208295 result . push ( paragraphs [ i ] ) ;
209296 i ++ ;
0 commit comments