@@ -32,7 +32,6 @@ interface VSCodeAttribute {
3232 name : string ;
3333 description ?: string | { kind : 'markdown' | 'plaintext' ; value : string } ;
3434 values ?: VSCodeAttributeValue [ ] ;
35- valueSet ?: string ;
3635 references ?: VSCodeReference [ ] ;
3736}
3837
@@ -53,11 +52,12 @@ const DOCS_BASE_URL = 'https://pine-design-system.netlify.app';
5352// Cache for component tag -> storybook title mapping
5453let storyTitleCache : Map < string , string > | null = null ;
5554
56- // Cache for component tag -> MDX documentation content
57- let mdxDocsCache : Map < string , string > | null = null ;
58-
59- // Cache for component tag -> example headings from MDX
60- let mdxExamplesCache : Map < string , string [ ] > | null = null ;
55+ // Cache for component tag -> parsed MDX data (docs and examples)
56+ interface MdxParsedData {
57+ docs : string ;
58+ examples : string [ ] ;
59+ }
60+ let mdxCache : Map < string , MdxParsedData > | null = null ;
6161
6262/**
6363 * Find the MDX documentation file for a component
@@ -140,8 +140,7 @@ function parseMdxToMarkdown(mdxContent: string): string {
140140 let foundHeader = false ;
141141 const paragraphLines : string [ ] = [ ] ;
142142
143- for ( let i = 0 ; i < lines . length ; i ++ ) {
144- const line = lines [ i ] ;
143+ for ( const line of lines ) {
145144 const trimmedLine = line . trim ( ) ;
146145
147146 // Skip import statements and JSX at the top
@@ -175,80 +174,38 @@ function parseMdxToMarkdown(mdxContent: string): string {
175174}
176175
177176/**
178- * Build a cache mapping component tags to their parsed MDX documentation
177+ * Get parsed MDX data for a component (with caching).
178+ * Reads and parses the MDX file once, extracting both docs and examples.
179179 */
180- function buildMdxDocsCache ( ) : Map < string , string > {
181- if ( mdxDocsCache ) {
182- return mdxDocsCache ;
180+ function getMdxData ( componentTag : string ) : MdxParsedData {
181+ if ( ! mdxCache ) {
182+ mdxCache = new Map ( ) ;
183183 }
184184
185- mdxDocsCache = new Map ( ) ;
186- return mdxDocsCache ;
187- }
188-
189- /**
190- * Get parsed MDX documentation for a component (with caching)
191- */
192- function getMdxDocs ( componentTag : string ) : string | null {
193- const cache = buildMdxDocsCache ( ) ;
194-
195- if ( cache . has ( componentTag ) ) {
196- return cache . get ( componentTag ) || null ;
185+ const cached = mdxCache . get ( componentTag ) ;
186+ if ( cached ) {
187+ return cached ;
197188 }
198189
199- const mdxPath = findMdxFile ( componentTag ) ;
200- if ( mdxPath === null ) {
201- cache . set ( componentTag , '' ) ;
202- return null ;
203- }
204-
205- try {
206- const mdxContent = fs . readFileSync ( mdxPath , 'utf-8' ) ;
207- const parsed = parseMdxToMarkdown ( mdxContent ) ;
208- cache . set ( componentTag , parsed ) ;
209- return parsed ;
210- } catch {
211- cache . set ( componentTag , '' ) ;
212- return null ;
213- }
214- }
215-
216- /**
217- * Build the examples cache
218- */
219- function buildMdxExamplesCache ( ) : Map < string , string [ ] > {
220- if ( mdxExamplesCache ) {
221- return mdxExamplesCache ;
222- }
223-
224- mdxExamplesCache = new Map ( ) ;
225- return mdxExamplesCache ;
226- }
227-
228- /**
229- * Get example headings from MDX for a component (with caching)
230- */
231- function getMdxExamples ( componentTag : string ) : string [ ] {
232- const cache = buildMdxExamplesCache ( ) ;
233-
234- if ( cache . has ( componentTag ) ) {
235- return cache . get ( componentTag ) || [ ] ;
236- }
190+ const emptyData : MdxParsedData = { docs : '' , examples : [ ] } ;
237191
238192 const mdxPath = findMdxFile ( componentTag ) ;
239- if ( mdxPath === null ) {
240- cache . set ( componentTag , [ ] ) ;
241- return [ ] ;
193+ if ( ! mdxPath ) {
194+ mdxCache . set ( componentTag , emptyData ) ;
195+ return emptyData ;
242196 }
243197
244198 try {
245199 const mdxContent = fs . readFileSync ( mdxPath , 'utf-8' ) ;
246- const examples = parseMdxExamples ( mdxContent ) ;
247- cache . set ( componentTag , examples ) ;
248- return examples ;
200+ const data : MdxParsedData = {
201+ docs : parseMdxToMarkdown ( mdxContent ) ,
202+ examples : parseMdxExamples ( mdxContent ) ,
203+ } ;
204+ mdxCache . set ( componentTag , data ) ;
205+ return data ;
249206 } catch {
250- cache . set ( componentTag , [ ] ) ;
251- return [ ] ;
207+ mdxCache . set ( componentTag , emptyData ) ;
208+ return emptyData ;
252209 }
253210}
254211
@@ -368,19 +325,19 @@ function formatPropDescription(prop: JsonDocsProp): string {
368325 const parts : string [ ] = [ ] ;
369326
370327 // Main description
371- if ( prop . docs !== undefined && prop . docs !== '' ) {
328+ if ( prop . docs ) {
372329 parts . push ( prop . docs ) ;
373330 }
374331
375- // Type info
376- if ( prop . type !== undefined && prop . type !== '' && prop . type !== 'string' && prop . type !== 'boolean' ) {
332+ // Type info (skip common primitive types)
333+ if ( prop . type && prop . type !== 'string' && prop . type !== 'boolean' ) {
377334 parts . push ( `\n\n**Type:** \`${ prop . type } \`` ) ;
378335 }
379336
380337 // Default value
381338 const defaultTag = prop . docsTags ?. find ( ( t ) => t . name === 'default' ) ;
382- if ( ( defaultTag ?. text !== undefined && defaultTag . text !== '' ) || prop . default !== undefined ) {
383- const defaultValue = defaultTag ?. text ?? prop . default ;
339+ const defaultValue = defaultTag ? .text || prop . default ;
340+ if ( defaultValue ) {
384341 parts . push ( `\n\n**Default:** \`${ defaultValue } \`` ) ;
385342 }
386343
@@ -395,23 +352,18 @@ function formatPropDescription(prop: JsonDocsProp): string {
395352
396353function formatComponentDescription ( component : JsonDocsComponent ) : string {
397354 const parts : string [ ] = [ ] ;
355+ const mdxData = getMdxData ( component . tag ) ;
398356
399- // Try to get rich MDX documentation first
400- const mdxDocs = getMdxDocs ( component . tag ) ;
401-
402- if ( mdxDocs !== null && mdxDocs !== '' ) {
403- parts . push ( mdxDocs ) ;
404- } else {
405- // Fallback to JSDoc description
406- if ( component . docs !== undefined && component . docs !== '' ) {
407- parts . push ( component . docs ) ;
408- }
357+ // Try to get rich MDX documentation first, fallback to JSDoc description
358+ if ( mdxData . docs ) {
359+ parts . push ( mdxData . docs ) ;
360+ } else if ( component . docs ) {
361+ parts . push ( component . docs ) ;
409362 }
410363
411364 // Add Examples section with links to MDX example headings
412- const examples = getMdxExamples ( component . tag ) ;
413- if ( examples . length > 0 ) {
414- const exampleLinks = examples . map ( ( heading ) => {
365+ if ( mdxData . examples . length > 0 ) {
366+ const exampleLinks = mdxData . examples . map ( ( heading ) => {
415367 const url = getExampleUrl ( component . tag , heading ) ;
416368 return `[${ heading } ](${ url } )` ;
417369 } ) ;
@@ -518,17 +470,13 @@ function convertComponent(component: JsonDocsComponent): VSCodeTag | null {
518470 }
519471 }
520472
521- // Add slot attributes for named slots (helps with autocomplete for slot="...")
522- // This is a bonus - VS Code will suggest slot names!
523-
524473 return tag ;
525474}
526475
527476export function generateVSCodeCustomData ( docs : JsonDocs , outputPath : string ) : void {
528477 // Reset caches for fresh generation
529478 storyTitleCache = null ;
530- mdxDocsCache = null ;
531- mdxExamplesCache = null ;
479+ mdxCache = null ;
532480
533481 const customData : VSCodeCustomData = {
534482 version : 1.1 ,
0 commit comments