mirror of
				https://github.com/Redocly/redoc.git
				synced 2025-11-04 09:47:31 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			126 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
import {RedocComponent, BaseComponent} from '../base';
 | 
						|
import SchemaManager from '../../utils/SchemaManager';
 | 
						|
 | 
						|
import ApiInfo from '../ApiInfo/api-info';
 | 
						|
import ApiLogo from '../ApiLogo/api-logo';
 | 
						|
import MethodsList from '../MethodsList/methods-list';
 | 
						|
import SideMenu from '../SideMenu/side-menu';
 | 
						|
import StickySidebar from '../../common/components/StickySidebar/sticky-sidebar';
 | 
						|
import OptionsManager from '../../options';
 | 
						|
import {redocEvents} from '../../events';
 | 
						|
 | 
						|
import {ChangeDetectionStrategy} from 'angular2/core';
 | 
						|
import {ElementRef} from 'angular2/core';
 | 
						|
import {BrowserDomAdapter, bootstrap} from 'angular2/platform/browser';
 | 
						|
import detectScollParent from 'scrollparent';
 | 
						|
 | 
						|
import {isFunction} from 'angular2/src/facade/lang';
 | 
						|
 | 
						|
let optionNames = new Set(['scrollYOffset']);
 | 
						|
 | 
						|
@RedocComponent({
 | 
						|
  selector: 'redoc',
 | 
						|
  providers: [SchemaManager, BrowserDomAdapter, OptionsManager],
 | 
						|
  templateUrl: './lib/components/Redoc/redoc.html',
 | 
						|
  styleUrls: ['./lib/components/Redoc/redoc.css'],
 | 
						|
  directives: [ApiInfo, ApiLogo, MethodsList, SideMenu, StickySidebar],
 | 
						|
  changeDetection: ChangeDetectionStrategy.Default
 | 
						|
})
 | 
						|
export default class Redoc extends BaseComponent {
 | 
						|
  constructor(schemaMgr, optionsMgr, elementRef, dom) {
 | 
						|
    super(schemaMgr);
 | 
						|
    this.element = elementRef.nativeElement;
 | 
						|
 | 
						|
    this.dom = dom;
 | 
						|
    let el = this.element;
 | 
						|
 | 
						|
    //parse options (top level component doesn't support inputs)
 | 
						|
    this.scrollParent = detectScollParent(el);
 | 
						|
    this.parseOptions();
 | 
						|
    this.options = Object.assign({}, optionsMgr.options, this.options);
 | 
						|
    this.normalizeOptions();
 | 
						|
  }
 | 
						|
 | 
						|
  parseOptions() {
 | 
						|
    let attributesMap = this.dom.attributeMap(this.element);
 | 
						|
    this.options = {};
 | 
						|
    Array.from(attributesMap.keys())
 | 
						|
      //camelCasify
 | 
						|
      .map(k => ({
 | 
						|
        attrName: k,
 | 
						|
        name: k.replace(/-(.)/g,  (m, $1) => $1.toUpperCase())
 | 
						|
        })
 | 
						|
      )
 | 
						|
      .filter(option => optionNames.has(option.name))
 | 
						|
      .forEach(option => {
 | 
						|
        this.options[option.name] = attributesMap.get(option.attrName);
 | 
						|
      });
 | 
						|
  }
 | 
						|
 | 
						|
  normalizeOptions() {
 | 
						|
    // modify scrollYOffset to always be a function
 | 
						|
    if (!isFunction(this.options.scrollYOffset)) {
 | 
						|
      if (isFinite(this.options.scrollYOffset)) {
 | 
						|
        // if number specified create function that returns this value
 | 
						|
        let numberOffset = parseFloat(this.options.scrollYOffset);
 | 
						|
        this.options.scrollYOffset = () => numberOffset;
 | 
						|
      } else {
 | 
						|
        // if selector or node function that returns bottom offset of this node
 | 
						|
        let el = this.options.scrollYOffset;
 | 
						|
        if (!(el instanceof Node)) {
 | 
						|
          el = this.dom.query(el);
 | 
						|
        }
 | 
						|
        if (!el) {
 | 
						|
          this.options.scrollYOffset = () => 0;
 | 
						|
        } else {
 | 
						|
          this.options.scrollYOffset = () => el.offsetTop + el.offsetHeight;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  static init(schemaUrl, options) {
 | 
						|
    if (Redoc.appRef) {
 | 
						|
      Redoc.dispose();
 | 
						|
    }
 | 
						|
    return SchemaManager.instance().load(schemaUrl)
 | 
						|
    .then(() => {
 | 
						|
      (new OptionsManager()).options = options;
 | 
						|
      return bootstrap(Redoc);
 | 
						|
    })
 | 
						|
    .then(
 | 
						|
      (appRef) => {
 | 
						|
        Redoc.appRef = appRef;
 | 
						|
        redocEvents.bootstrapped.next();
 | 
						|
        console.log('ReDoc bootstrapped!');
 | 
						|
      },
 | 
						|
      error => {
 | 
						|
        console.log(error);
 | 
						|
        throw error;
 | 
						|
      }
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  static dispose() {
 | 
						|
    let dom = new BrowserDomAdapter();
 | 
						|
    let el = dom.query('redoc');
 | 
						|
    let parent = el.parentElement;
 | 
						|
    let nextSibling = el.nextElementSibling;
 | 
						|
 | 
						|
    Redoc.appRef && Redoc.appRef.dispose();
 | 
						|
    Redoc.appRef = null;
 | 
						|
 | 
						|
    // Redoc dispose removes host element, so need to restore it
 | 
						|
    el = dom.createElement('redoc');
 | 
						|
    el.innerText = 'Loading...';
 | 
						|
    parent.insertBefore(el, nextSibling);
 | 
						|
  }
 | 
						|
}
 | 
						|
Redoc.parameters = Redoc.parameters.concat([[OptionsManager], [ElementRef], [BrowserDomAdapter]]);
 | 
						|
 | 
						|
// TODO
 | 
						|
// this doesn't work in side-menu.js because of some circular references issue
 | 
						|
SideMenu.parameters = SideMenu.parameters.concat([[Redoc]]);
 |