UNPKG

amis

Version:

一种MIS页面生成工具

191 lines (165 loc) 7.04 kB
/* eslint-disable no-unused-vars */ import React from 'react'; import ReactDOM from 'react-dom'; import {render} from '../../src/index'; import axios from 'axios'; import TitleBar from '../../src/components/TitleBar'; import LazyComponent from '../../src/components/LazyComponent'; import Overlay from '../../src/components/Overlay'; import PopOver from '../../src/components/PopOver'; import NestedLinks from '../../src/components/AsideNav'; import {Portal} from 'react-overlays'; class CodePreview extends React.Component { state = { PlayGround: null }; componentDidMount() { require(['./Play'], (component) => this.setState({ PlayGround: component.default })) } render() { const { container, height, setAsideFolded, setHeaderVisible, ...rest } = this.props; const PlayGround = this.state.PlayGround; // 不要放在 .markdown-body 下面,因为样式会干扰,复写又麻烦,所以通过 Overlay 渲染到同级 return ( <div> <span style={{display: 'block', height: height}} ref="span"></span> {PlayGround ? <Overlay container={container} target={() => this.refs.span} placement="bottom" show > <PopOver offset={{x: 0, y: -height}} style={{height}} className="doc-shcema-preview-popover"> <div className="doc-schema-preview"> <PlayGround {...rest} vertical /> </div> </PopOver> </Overlay> : null } </div> ); } } function isActive(link, location) { return !!(link.fullPath && link.fullPath === location.hash); } export default function(doc) { return class extends React.Component { static displayName = 'MarkdownRenderer'; ref = null; doms = []; constructor(props) { super(props); this.divRef = this.divRef.bind(this); this.handleClick = this.handleClick.bind(this); } componentDidMount() { this.renderSchema(); if (location.hash && location.hash.length > 1) { // 禁用自动跳转 if (window.history && 'scrollRestoration' in window.history) { window.history.scrollRestoration = 'manual'; } const dom = document.querySelector(`[name="${location.hash.substring(1)}"]`); dom && dom.scrollIntoView(); } } componentDidUpdate() { this.renderSchema(); } componentWillUnmount() { this.doms.forEach(dom => ReactDOM.unmountComponentAtNode(dom)); } handleClick(e) { const href = e.target.getAttribute('href'); if (href && href[0] !== '#' && !/^http/.test(href)) { e.preventDefault(); this.props.push(href); } } divRef(ref) { this.ref = ref; if (ref) { ref.innerHTML = doc.html; } } renderSchema() { const scripts = document.querySelectorAll('script[type="text/schema"]'); if (!scripts && !scripts.length) { return; } for (let i = 0, len = scripts.length; i < len; i++) { let script = scripts[i]; let props = {}; [].slice.apply(script.attributes).forEach(item => { props[item.name] = item.value }); let dom = document.createElement('div'); let height = props.height ? parseInt(props.height, 10) : 200; dom.setAttribute("class", "doc-play-ground") dom.setAttribute("style", `height: ${height}px;`); script.parentNode.replaceChild(dom, script); this.doms.push(dom); ReactDOM.unstable_renderSubtreeIntoContainer(this, ( <LazyComponent {...this.props} container={() => ReactDOM.findDOMNode(this)} height={height} component={CodePreview} code={script.innerText} scope={props.scope} unMountOnHidden placeholder="加载中,请稍后。。。" /> ), dom); } } render() { const {location} = this.props; return ( <div className="pos-rlt text-left"> {doc.title ? (<TitleBar title={doc.title} />) : null} <div className="markdown-body" ref={this.divRef}>Doc</div> {doc.toc && doc.toc.children && doc.toc.children.length > 1 ? ( <Portal container={() => document.querySelector('#asideInner')} > <NestedLinks navigations={[doc.toc]} renderLink={({link, active, toggleExpand, depth, classnames: cx}) => { let children = []; if (link.children) { children.push( <span key="expand-toggle" className={cx(`AsideNav-itemArrow`)} ></span> ); } link.badge && children.push( <b key="badge" className={cx('AsideNav-itemBadge', link.badgeClassName || 'bg-info')}>{link.badge}</b> ); depth === 1 && children.push( <i key="icon" className={cx("AsideNav-itemIcon fa fa-flag")} /> ); children.push( <span key="label" className={cx("AsideNav-itemLabel")}>{link.label}</span> ); return link.fragment ? (<a href={`#${link.fragment}`}>{children}</a>) : (<a onClick={link.children ? () => toggleExpand(link) : null}>{children}</a>); }} isActive={link => isActive(link, location)} /> </Portal> ) : null} </div> ); } } }