mirror of
				https://github.com/Redocly/redoc.git
				synced 2025-10-31 15:57:30 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			130 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| import { Component, Input, Renderer, ElementRef, OnInit, ChangeDetectionStrategy } from '@angular/core';
 | |
| 
 | |
| import { BaseComponent, SpecManager } from '../base';
 | |
| import { SchemaNormalizer, SchemaHelper } from '../../services/index';
 | |
| 
 | |
| @Component({
 | |
|   selector: 'json-schema',
 | |
|   templateUrl: './json-schema.html',
 | |
|   styleUrls: ['./json-schema.css'],
 | |
|   changeDetection: ChangeDetectionStrategy.OnPush
 | |
| })
 | |
| export class JsonSchema extends BaseComponent implements OnInit {
 | |
|   @Input() pointer: string;
 | |
|   @Input() final: boolean = false;
 | |
|   @Input() nestOdd: boolean;
 | |
|   @Input() childFor: string;
 | |
|   @Input() isRequestSchema: boolean;
 | |
| 
 | |
|   schema: any = {};
 | |
|   activeDescendant:any = {};
 | |
|   hasDescendants: boolean = false;
 | |
|   _hasSubSchemas: boolean = false;
 | |
|   properties: any;
 | |
|   _isArray: boolean;
 | |
|   normalizer: SchemaNormalizer;
 | |
|   autoExpand = false;
 | |
|   descendants: any;
 | |
| 
 | |
|   constructor(specMgr:SpecManager, private _renderer: Renderer, private _elementRef: ElementRef) {
 | |
|     super(specMgr);
 | |
|     this.normalizer = new SchemaNormalizer(specMgr);
 | |
|   }
 | |
| 
 | |
|   get normPointer() {
 | |
|     return this.schema._pointer || this.pointer;
 | |
|   }
 | |
| 
 | |
|   selectDescendant(idx) {
 | |
|     let activeDescendant = this.descendants[idx];
 | |
|     if (!activeDescendant || activeDescendant.active) return;
 | |
|     this.descendants.forEach(d => {
 | |
|       d.active = false;
 | |
|     });
 | |
|     activeDescendant.active = true;
 | |
| 
 | |
|     this.pointer = activeDescendant.$ref;
 | |
|     this.schema = this.specMgr.byPointer(this.pointer);
 | |
|     this.normalizer.reset();
 | |
|     this.schema = this.normalizer.normalize(this.schema, this.normPointer,
 | |
|       {resolved: true});
 | |
|     this.preprocessSchema();
 | |
|   }
 | |
| 
 | |
|   initDescendants() {
 | |
|     this.descendants = this.specMgr.findDerivedDefinitions(this.normPointer);
 | |
|     if (!this.descendants.length) return;
 | |
|     this.hasDescendants = true;
 | |
|     let discriminator = this.schema.discriminator || this.schema['x-extendedDiscriminator'];
 | |
|     let discrProperty = this.schema._properties &&
 | |
|       this.schema._properties.filter((prop) => prop.name === discriminator)[0];
 | |
|     if (discrProperty && discrProperty.enum) {
 | |
|       let enumOrder = {};
 | |
|       discrProperty.enum.forEach((enumItem, idx) => {
 | |
|         enumOrder[enumItem.val] = idx;
 | |
|       });
 | |
| 
 | |
|       this.schema._descendants.sort((a, b) => {
 | |
|         return enumOrder[a.name] > enumOrder[b.name] ? 1 : -1;
 | |
|       });
 | |
|     }
 | |
|     this.selectDescendant(0);
 | |
|   }
 | |
| 
 | |
|   init() {
 | |
|     if (!this.pointer) return;
 | |
|     this.schema = this.componentSchema;
 | |
|     if (!this.schema) {
 | |
|       throw new Error(`Can't load component schema at ${this.pointer}`);
 | |
|     }
 | |
| 
 | |
|     this.applyStyling();
 | |
| 
 | |
|     this.schema = this.normalizer.normalize(this.schema, this.normPointer, {resolved: true});
 | |
|     this.schema = SchemaHelper.unwrapArray(this.schema, this.normPointer);
 | |
|     this.initDescendants();
 | |
|     this.preprocessSchema();
 | |
|   }
 | |
| 
 | |
|   preprocessSchema() {
 | |
|     SchemaHelper.preprocess(this.schema, this.normPointer, this.pointer);
 | |
| 
 | |
|     if (!this.schema.isTrivial) {
 | |
|       SchemaHelper.preprocessProperties(this.schema, this.normPointer, {
 | |
|         childFor: this.childFor
 | |
|       });
 | |
|     }
 | |
| 
 | |
|     this.properties = this.schema._properties;
 | |
|     if (this.isRequestSchema) {
 | |
|       this.properties = this.properties && this.properties.filter(prop => !prop.readOnly);
 | |
|     }
 | |
| 
 | |
|     this._hasSubSchemas = this.properties && this.properties.some(
 | |
|       propSchema => {
 | |
|         if (propSchema.type === 'array') {
 | |
|           propSchema = propSchema.items;
 | |
|         }
 | |
|         return (propSchema && propSchema.type === 'object' && propSchema._pointer);
 | |
|       });
 | |
| 
 | |
|     this.autoExpand = this.properties && this.properties.length === 1;
 | |
|   }
 | |
| 
 | |
|   applyStyling() {
 | |
|     if (this.nestOdd) {
 | |
|       this._renderer.setElementAttribute(this._elementRef.nativeElement, 'nestodd', 'true');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   trackByName(index: number, item: any): number {
 | |
|     return item.name + (item._pointer || '');
 | |
|   }
 | |
| 
 | |
|   ngOnInit() {
 | |
|     this.preinit();
 | |
|   }
 | |
| }
 |