@@ -8,6 +8,14 @@ const slugify = (text) =>
88
99const isObject = ( v ) => v && typeof v === 'object' && ! Array . isArray ( v ) ;
1010
11+ const refToDefName = ( ref ) => {
12+ if ( typeof ref !== 'string' ) return null ;
13+ if ( ref . startsWith ( '#/$defs/' ) ) return ref . slice ( '#/$defs/' . length ) ;
14+ if ( ref . startsWith ( '#/definitions/' ) )
15+ return ref . slice ( '#/definitions/' . length ) ;
16+ return null ;
17+ } ;
18+
1119function formatType ( cellSchema ) {
1220 if ( ! cellSchema ) return 'N/A' ;
1321
@@ -206,7 +214,13 @@ function Markdown({ text }) {
206214 return < span dangerouslySetInnerHTML = { { __html : markdownToHtml ( text ) } } /> ;
207215}
208216
209- function PropertiesTable ( { title, description, properties, required } ) {
217+ function PropertiesTable ( {
218+ title,
219+ description,
220+ properties,
221+ required,
222+ defaults,
223+ } ) {
210224 if ( ! properties || Object . keys ( properties ) . length === 0 ) return null ;
211225
212226 return (
@@ -242,10 +256,42 @@ function PropertiesTable({ title, description, properties, required }) {
242256 const isRequired = Array . isArray ( required )
243257 ? required . includes ( name )
244258 : false ;
245- const defaultValue =
259+ const explicitDefault =
246260 schema && Object . prototype . hasOwnProperty . call ( schema , 'default' )
247- ? JSON . stringify ( schema . default )
248- : 'N/A' ;
261+ ? schema . default
262+ : undefined ;
263+ const inferredDefault =
264+ defaults && Object . prototype . hasOwnProperty . call ( defaults , name )
265+ ? defaults [ name ]
266+ : undefined ;
267+ const chosenDefault =
268+ explicitDefault !== undefined
269+ ? explicitDefault
270+ : inferredDefault !== undefined
271+ ? inferredDefault
272+ : undefined ;
273+
274+ // Link to the referenced definition for non-primitive defaults (objects/arrays) when possible
275+ let defaultCell ;
276+ if ( chosenDefault === undefined ) {
277+ defaultCell = 'N/A' ;
278+ } else if (
279+ typeof chosenDefault === 'object' &&
280+ chosenDefault !== null
281+ ) {
282+ const defName = schema ? refToDefName ( schema . $ref ) : null ;
283+ if ( defName ) {
284+ defaultCell = (
285+ < >
286+ See < a href = { `#${ slugify ( defName ) } ` } > { defName } </ a >
287+ </ >
288+ ) ;
289+ } else {
290+ defaultCell = JSON . stringify ( chosenDefault ) ;
291+ }
292+ } else {
293+ defaultCell = JSON . stringify ( chosenDefault ) ;
294+ }
249295
250296 return (
251297 < tr key = { name } >
@@ -265,7 +311,7 @@ function PropertiesTable({ title, description, properties, required }) {
265311 < td className = "manifest-ref-table" >
266312 { isRequired ? 'YES' : 'NO' }
267313 </ td >
268- < td className = "manifest-ref-table" > { defaultValue } </ td >
314+ < td className = "manifest-ref-table" > { defaultCell } </ td >
269315 </ tr >
270316 ) ;
271317 } ) }
@@ -402,6 +448,7 @@ function DefinitionSection({ name, schema }) {
402448 < PropertiesTable
403449 properties = { schema . properties || { } }
404450 required = { schema . required || [ ] }
451+ defaults = { schema . __inferredDefaults || undefined }
405452 />
406453 ) : (
407454 // Fallback simple table for non-object schemas
@@ -445,6 +492,54 @@ export default function SchemaReference({ schemaUrl }) {
445492 const [ error , setError ] = useState ( null ) ;
446493 const [ loading , setLoading ] = useState ( true ) ;
447494
495+ const buildDefDefaults = ( root ) => {
496+ if ( ! root || ! isObject ( root ) ) return { } ;
497+ const defs = root . $defs || root . definitions || { } ;
498+ const defDefaults = { } ;
499+
500+ const feed = ( defName , defSchema , value ) => {
501+ if ( ! defName || ! defSchema ) return ;
502+ if ( ! isObject ( value ) ) {
503+ // Record scalar/array as the default value of the referenced node when used as a property.
504+ // For nested object defaults we handle below.
505+ return ;
506+ }
507+ const props = ( defSchema && defSchema . properties ) || { } ;
508+ if ( ! isObject ( props ) ) return ;
509+ if ( ! defDefaults [ defName ] ) defDefaults [ defName ] = { } ;
510+ for ( const [ propName , propSchema ] of Object . entries ( props ) ) {
511+ if ( ! Object . prototype . hasOwnProperty . call ( value , propName ) ) continue ;
512+ const propValue = value [ propName ] ;
513+ // Always record the value for the property at this level for display
514+ defDefaults [ defName ] [ propName ] = propValue ;
515+ // If the property itself references another definition and the default value is an object,
516+ // propagate deeper so nested definition sections can show their own inferred defaults.
517+ const subRefName = propSchema && refToDefName ( propSchema . $ref ) ;
518+ if ( subRefName ) {
519+ const subDefSchema = defs [ subRefName ] ;
520+ if ( subDefSchema ) feed ( subRefName , subDefSchema , propValue ) ;
521+ }
522+ }
523+ } ;
524+
525+ const rootProps = ( root && root . properties ) || { } ;
526+ for ( const [ , propSchema ] of Object . entries ( rootProps ) ) {
527+ const defName = propSchema && refToDefName ( propSchema . $ref ) ;
528+ if ( ! defName ) continue ;
529+ const defSchema = defs [ defName ] ;
530+ if ( ! defSchema ) continue ;
531+ if (
532+ propSchema &&
533+ Object . prototype . hasOwnProperty . call ( propSchema , 'default' )
534+ ) {
535+ const defaultValue = propSchema . default ;
536+ feed ( defName , defSchema , defaultValue ) ;
537+ }
538+ }
539+
540+ return defDefaults ;
541+ } ;
542+
448543 useEffect ( ( ) => {
449544 let cancelled = false ;
450545 async function run ( ) {
@@ -467,6 +562,11 @@ export default function SchemaReference({ schemaUrl }) {
467562 } ;
468563 } , [ schemaUrl ] ) ;
469564
565+ const inferredDefaults = useMemo (
566+ ( ) => buildDefDefaults ( schema || { } ) ,
567+ [ schema ] ,
568+ ) ;
569+
470570 if ( loading ) return < p > Loading schema…</ p > ;
471571 if ( error ) return < p style = { { color : 'red' } } > { error } </ p > ;
472572 if ( ! schema ) return < p > No schema loaded.</ p > ;
@@ -496,9 +596,21 @@ export default function SchemaReference({ schemaUrl }) {
496596
497597 < DefinitionsTOC defs = { defs } />
498598
499- { Object . entries ( defs ) . map ( ( [ name , defSchema ] ) => (
500- < DefinitionSection key = { name } name = { name } schema = { defSchema } />
501- ) ) }
599+ { Object . entries ( defs ) . map ( ( [ name , defSchema ] ) => {
600+ const schemaWithDefaults =
601+ ( defSchema && {
602+ ...defSchema ,
603+ __inferredDefaults : inferredDefaults [ name ] ,
604+ } ) ||
605+ defSchema ;
606+ return (
607+ < DefinitionSection
608+ key = { name }
609+ name = { name }
610+ schema = { schemaWithDefaults }
611+ />
612+ ) ;
613+ } ) }
502614 </ div >
503615 ) ;
504616}
0 commit comments