2019-04-30 11:11:25 +08:00
|
|
|
/* eslint-disable no-unused-vars */
|
2019-06-11 17:00:02 +08:00
|
|
|
import React from 'react';
|
|
|
|
import ReactDOM from 'react-dom';
|
2019-04-30 11:11:25 +08:00
|
|
|
import {render} from '../../src/index';
|
2019-06-11 17:00:02 +08:00
|
|
|
import axios from 'axios';
|
2019-04-30 11:11:25 +08:00
|
|
|
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';
|
2020-07-23 20:31:51 +08:00
|
|
|
import classnames from 'classnames';
|
2020-07-28 14:55:49 +08:00
|
|
|
import {Link} from 'react-router';
|
2019-04-30 11:11:25 +08:00
|
|
|
|
|
|
|
class CodePreview extends React.Component {
|
2019-11-07 10:41:14 +08:00
|
|
|
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" />
|
|
|
|
{PlayGround ? (
|
|
|
|
<Overlay
|
|
|
|
container={container}
|
|
|
|
target={() => this.refs.span}
|
|
|
|
placement="bottom"
|
|
|
|
show
|
|
|
|
>
|
|
|
|
<PopOver
|
2020-07-24 17:20:08 +08:00
|
|
|
offset={{x: 0, y: -height}}
|
2019-11-07 10:41:14 +08:00
|
|
|
style={{height}}
|
2020-07-23 20:31:51 +08:00
|
|
|
className=":MDPreview-shcema-preview-popover"
|
2019-11-07 10:41:14 +08:00
|
|
|
>
|
2020-07-23 20:31:51 +08:00
|
|
|
<div className="MDPreview-schema-preview">
|
2019-11-07 10:41:14 +08:00
|
|
|
<PlayGround {...rest} vertical />
|
|
|
|
</div>
|
|
|
|
</PopOver>
|
|
|
|
</Overlay>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function isActive(link, location) {
|
2019-11-07 10:41:14 +08:00
|
|
|
return !!(link.fullPath && link.fullPath === location.hash);
|
2019-04-30 11:11:25 +08:00
|
|
|
}
|
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
class Preview 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);
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
componentDidMount() {
|
|
|
|
this.renderSchema();
|
2019-04-30 11:11:25 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
if (location.hash && location.hash.length > 1) {
|
|
|
|
// 禁用自动跳转
|
|
|
|
if (window.history && 'scrollRestoration' in window.history) {
|
|
|
|
window.history.scrollRestoration = 'manual';
|
2019-11-07 10:41:14 +08:00
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
const dom = document.querySelector(
|
|
|
|
`[name="${location.hash.substring(1)}"]`
|
|
|
|
);
|
|
|
|
dom && dom.scrollIntoView();
|
2019-11-07 10:41:14 +08:00
|
|
|
}
|
2020-07-24 17:20:08 +08:00
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
componentDidUpdate() {
|
|
|
|
this.renderSchema();
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
componentWillUnmount() {
|
|
|
|
this.doms.forEach(dom => ReactDOM.unmountComponentAtNode(dom));
|
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
handleClick(e) {
|
|
|
|
const href = e.target.getAttribute('href');
|
|
|
|
if (href && href[0] !== '#' && !/^http/.test(href)) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.props.push(href);
|
2019-11-07 10:41:14 +08:00
|
|
|
}
|
2020-07-24 17:20:08 +08:00
|
|
|
}
|
2019-04-30 11:11:25 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
divRef(ref) {
|
|
|
|
this.ref = ref;
|
2019-11-07 10:41:14 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
if (ref) {
|
|
|
|
ref.innerHTML = this.props.doc.html;
|
|
|
|
}
|
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
renderSchema() {
|
|
|
|
const scripts = document.querySelectorAll('script[type="text/schema"]');
|
|
|
|
if (!scripts && !scripts.length) {
|
|
|
|
return;
|
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
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}
|
|
|
|
height={height}
|
|
|
|
container={() => ReactDOM.findDOMNode(this)}
|
|
|
|
height={height}
|
|
|
|
component={CodePreview}
|
|
|
|
code={script.innerText}
|
|
|
|
scope={props.scope}
|
|
|
|
unMountOnHidden
|
|
|
|
placeholder="加载中,请稍后。。。"
|
|
|
|
/>,
|
|
|
|
dom
|
|
|
|
);
|
2019-11-07 10:41:14 +08:00
|
|
|
}
|
2020-07-24 17:20:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<div className="MDPreview">
|
|
|
|
<div className="markdown-body" ref={this.divRef}>
|
|
|
|
Doc
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
export default function (doc) {
|
|
|
|
return class extends React.Component {
|
2020-07-23 20:31:51 +08:00
|
|
|
renderHeading(children) {
|
|
|
|
return children.map((child, idx) => (
|
|
|
|
<div
|
|
|
|
key={`${child.fullPath}-${idx}`}
|
|
|
|
className={classnames('Doc-headingList-item', {
|
|
|
|
'is-active': this.props.location.hash === child.fullPath
|
|
|
|
})}
|
|
|
|
>
|
|
|
|
<a href={`#${child.fragment}`}>{child.label}</a>
|
|
|
|
|
|
|
|
{child.children && child.children.length
|
|
|
|
? this.renderHeading(child.children)
|
|
|
|
: null}
|
|
|
|
</div>
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
render() {
|
2020-07-28 14:55:49 +08:00
|
|
|
const {prevDoc, nextDoc} = this.props;
|
|
|
|
|
2019-11-07 10:41:14 +08:00
|
|
|
return (
|
2020-07-23 20:31:51 +08:00
|
|
|
<>
|
|
|
|
<div className="Doc-content">
|
|
|
|
{doc.title ? (
|
|
|
|
<div className="Doc-title">
|
|
|
|
<h1>{doc.title}</h1>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2020-07-28 14:55:49 +08:00
|
|
|
|
2020-07-24 17:20:08 +08:00
|
|
|
<Preview {...this.props} doc={doc} />
|
2020-07-28 14:55:49 +08:00
|
|
|
|
|
|
|
<div className="Doc-footer">
|
|
|
|
<div className="Doc-navLinks">
|
|
|
|
{prevDoc ? (
|
|
|
|
<Link className="Doc-navLinks--prev" to={prevDoc.path}>
|
|
|
|
<div className="Doc-navLinks-icon">
|
|
|
|
<i className="iconfont icon-arrow-left"></i>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="Doc-navLinks-body text-right">
|
|
|
|
<div className="Doc-navLinks-subtitle">
|
|
|
|
上一篇 - {prevDoc.group || '其他'}
|
|
|
|
</div>
|
|
|
|
<div className="Doc-navLinks-title">{prevDoc.label} </div>
|
|
|
|
</div>
|
|
|
|
</Link>
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
{nextDoc ? (
|
|
|
|
<Link className="Doc-navLinks--next" to={nextDoc.path}>
|
|
|
|
<div className="Doc-navLinks-body">
|
|
|
|
<div className="Doc-navLinks-subtitle">
|
|
|
|
下一篇 - {nextDoc.group || '其他'}
|
|
|
|
</div>
|
|
|
|
<div className="Doc-navLinks-title">{nextDoc.label}</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="Doc-navLinks-icon">
|
|
|
|
<i className="iconfont icon-arrow-right"></i>
|
|
|
|
</div>
|
|
|
|
</Link>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-11-07 10:41:14 +08:00
|
|
|
</div>
|
|
|
|
{doc.toc && doc.toc.children && doc.toc.children.length > 1 ? (
|
2020-07-23 20:31:51 +08:00
|
|
|
<div className="Doc-toc">
|
|
|
|
<div className="Doc-headingList">
|
|
|
|
{this.renderHeading(doc.toc.children)}
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-11-07 10:41:14 +08:00
|
|
|
) : null}
|
2020-07-23 20:31:51 +08:00
|
|
|
</>
|
2019-11-07 10:41:14 +08:00
|
|
|
);
|
2019-04-30 11:11:25 +08:00
|
|
|
}
|
2019-11-07 10:41:14 +08:00
|
|
|
};
|
2019-04-30 11:11:25 +08:00
|
|
|
}
|