amis2/examples/components/MdRenderer.jsx
liaoxuezhi c591ab4381
chore: 开发环境切成 vite (#5677)
* 尝试使用 vite 跑开发环境

* 尝试使用 vite 跑开发环境

* 尝试使用 vite 跑开发环境

* 尝试使用 vite 跑开发环境

* 样式文档调整

* 修复有多个 __inline 时的报错

* scirpt 调整

* feat:chart接入事件动作 (#5669)

* chore: input-group 没有 name 不应该报 warning (#5667)

* chore: 处理编译TS Warning,调整TableStore中label解析的顺序 (#5670)

* feat: timeline时间轴支持自定义图标 (#5668)

* fix:折叠器Collapse自定义图标&inputNumber对含后缀生效

* 修改

* 正则修改

* 正则修改

* 正则修改

* feat:将默认px替换为rem 2px===0.125rem

* feat:timeline时间轴支持自定义图标

Co-authored-by: xujiahao01 <xujiahao01@baidu.com>

* fix: 调整echarts-stat使用方式,兼容vite打包异步非esm模块 (#5672)

* feat: chart 支持配置加载 geojson 及百度地图 (#5674)

* feat: chart 支持配置 geoURL 及 geoName

* 增加百度地图配置

* chore: 修复 coverage 运行报错 (#5678)

* chore: coverage 执行换成 v8 解决内存问题 (#5679)

* 尝试使用 vite 跑开发环境

* amis-formula 也添加 esm 模块

* 代码合并有问题,做些调整

Co-authored-by: hsm-lv <80095014+hsm-lv@users.noreply.github.com>
Co-authored-by: 吴多益 <wuduoyi@baidu.com>
Co-authored-by: RUNZE LU <36724300+lurunze1226@users.noreply.github.com>
Co-authored-by: 徐佳豪 <1440054388@qq.com>
Co-authored-by: xujiahao01 <xujiahao01@baidu.com>
Co-authored-by: 刘丹 <365533093@qq.com>
2022-11-02 22:45:12 +08:00

386 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable no-unused-vars */
import React from 'react';
import {findDOMNode} from 'react-dom';
import {createRoot} from 'react-dom/client';
import {getTheme, render} from 'amis';
import {LazyComponent} from 'amis-core';
import {Overlay} from 'amis-core';
import {PopOver} from 'amis-core';
import classnames from 'classnames';
import {Link} from 'react-router-dom';
import Play from './Play';
class CodePreview extends React.Component {
state = {
PlayGround: null
};
render() {
const {container, setAsideFolded, setHeaderVisible, ...rest} = this.props;
return <Play {...rest} mini />;
}
}
function eachDom(dom, iterator) {
if (!dom) {
return;
}
iterator(dom);
if (dom.children && dom.children.length) {
[].slice.call(dom.children).forEach(dom => eachDom(dom, iterator));
}
}
class Preview extends React.Component {
static displayName = 'MarkdownRenderer';
ref = null;
roots = [];
constructor(props) {
super(props);
this.divRef = this.divRef.bind(this);
}
componentDidMount() {
this.renderSchema();
this.fixHtmlPreview();
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();
this.fixHtmlPreview();
}
componentWillUnmount() {
// 立即 unmout 会报错
window.requestAnimationFrame(() => {
this.roots.forEach(root => root.unmount());
});
}
divRef(ref) {
this.ref = ref;
if (ref) {
ref.innerHTML = this.props.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;
if (this.props.viewMode === 'mobile') {
// 移动端下高度不能太低
if (height < 500) {
height = 500;
}
}
dom.setAttribute('class', 'doc-play-ground');
// dom.setAttribute('style', `min-height: ${height}px;`);
const origin = script.parentNode;
origin.parentNode.replaceChild(dom, origin);
const root = createRoot(dom);
this.roots.push(root);
root.render(
<LazyComponent
{...this.props}
container={() => findDOMNode(this)}
component={CodePreview}
code={script.innerText}
scope={props.scope}
// unMountOnHidden
height={height}
placeholder="加载中,请稍后。。。"
/>
);
}
}
fixHtmlPreview() {
const htmlPreviews = document.querySelectorAll('.amis-doc>.preview');
if (!htmlPreviews && !htmlPreviews.length) {
return;
}
const ns = getTheme(this.props.theme)?.classPrefix;
[].slice.call(htmlPreviews).forEach(dom => {
eachDom(dom, dom => {
if (typeof dom.className !== 'string') {
return;
}
dom.className = dom.className.replace(
/(^|\s)([A-Z])/g,
'$1' + ns + '$2'
);
});
});
}
render() {
return (
<div className="MDPreview">
<div className="markdown" ref={this.divRef}>
Doc
</div>
</div>
);
}
}
export default function (doc) {
doc = doc.default || doc;
return class extends React.Component {
popoverDom = null;
originTitle = document.title;
state = {
headingPopover: false
};
popoverRef = ref => {
this.popoverDom = ref;
};
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>
));
}
handlePopOverClick = e => {
this.setState({headingPopover: false});
e.stopPropagation();
// e.preventDefault();
};
renderHeadingPopover() {
return this.state.headingPopover ? (
<Overlay
target={this.popoverDom}
container={this.popoverDom}
rootClose={false}
placement="right-bottom-right-top"
show
>
<PopOver
classPrefix="cxd-"
className=":Doc-headingPopover"
onHide={() => this.setState({headingPopover: false})}
overlay
onClick={this.handlePopOverClick}
>
{this.renderHeading(doc.toc.children)}
</PopOver>
</Overlay>
) : null;
}
componentDidMount() {
if (doc.title) {
document.title = doc.title;
}
}
componentWillUnmount() {
document.title = this.originTitle;
}
pathJoin(...parts) {
const separator = '/';
const normalizedParts = parts
.filter(
part =>
part != null &&
(typeof part === 'string' || typeof part === 'number')
)
.map((item, index, arr) => {
let part = `${item}`;
// 去除首个元素之外的"/"前缀
if (index > 0) {
part = part.replace(/^[\/]+/, '');
}
// 去除中间元素的"/"后缀,最后一个元素的多个"/"后缀改为1个
return index < arr.length - 1
? part.replace(/[\/]+$/, '')
: part.replace(/[\/]+$/, '/');
});
return normalizedParts.join(separator);
}
getDocEditLink() {
const {ContextPath} = this.props;
const basePath = 'https://github.com/baidu/amis/edit/master';
try {
const [urlPath, locale, moduleName, relativePath] = location.pathname
.replace(ContextPath, '')
.match(/^\/(zh-CN)\/(docs|components|style|)(([\/]?[\w-]+)*)/);
if (moduleName === 'docs') {
return this.pathJoin(
basePath,
`/docs/${locale}/`,
`${relativePath}.md`
);
} else if (
moduleName === 'style' &&
!/style\/(index|css-vars|responsive-design|state)$/.test(urlPath)
) {
const fileName = location.pathname.split('/')?.slice(-1)?.[0];
return this.pathJoin(
basePath,
`/packages/amis-ui/scss/helper`,
relativePath.replace(fileName, `/_${fileName}.scss`)
);
} else {
return this.pathJoin(
basePath,
`/docs/${locale}/${moduleName}`,
`/${relativePath}.md`
);
}
} catch (error) {
return this.pathJoin(basePath, 'docs');
}
}
render() {
const {prevDoc, nextDoc, ContextPath} = this.props;
return (
<>
<div className="Doc-content">
{doc.title ? (
<div className="Doc-title">
<h1>{doc.title}</h1>
{doc?.toc.children?.length ? (
<div
ref={this.popoverRef}
onClick={e =>
this.setState({
headingPopover: !this.state.headingPopover
})
}
className="Doc-headingPopBtn visible-xs"
>
<i className="fa fa-align-right"></i>
{this.renderHeadingPopover()}
</div>
) : null}
</div>
) : null}
<Preview {...this.props} doc={doc} />
<div className="Doc-footer">
<div className="Doc-navLinks">
{prevDoc ? (
<Link
className="Doc-navLinks--prev"
to={`${ContextPath}${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={`${ContextPath}${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 className="Doc-footer-divider"></div>
<div className="Doc-footer-fixme">
文档有误
<a
href={this.getDocEditLink()}
rel="noopener noreferrer"
target="_blank"
>
Github 上编辑此页
</a>
</div>
</div>
</div>
{doc.toc && doc.toc.children && doc.toc.children.length > 0 ? (
<div className="Doc-toc hidden-xs hidden-sm">
<div>
<div className="Doc-headingList">
{this.renderHeading(doc.toc.children)}
</div>
</div>
</div>
) : null}
</>
);
}
};
}