mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 14:13:37 +08:00
Merge pull request #1869 from ant-design/revert-1745-refactor-bisheng
Revert "refactor with bisheng"
This commit is contained in:
commit
7bed6d89b5
2
.gitignore
vendored
2
.gitignore
vendored
@ -23,6 +23,6 @@ nohup.out
|
||||
_site
|
||||
_data
|
||||
dist
|
||||
/lib
|
||||
lib
|
||||
elasticsearch-*
|
||||
config/base.yaml
|
||||
|
9
404.html
Normal file
9
404.html
Normal file
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
var prefix = /^\/components/.test(location.pathname) ? location.pathname.replace(/^\//, '').split('/').join('-') : '';
|
||||
var scrollToString = location.hash ? '?scrollTo=' + prefix + location.hash : '';
|
||||
if (location.pathname === '/changelog') {
|
||||
location.href = '/#/docs/react/changelog' + scrollToString;
|
||||
} else {
|
||||
location.href = '/#' + location.pathname.replace(/\/$/, '') + scrollToString;
|
||||
}
|
||||
</script>
|
@ -40,7 +40,7 @@ english: Icon
|
||||
### 一. 方向性图标
|
||||
|
||||
```__react
|
||||
import IconSet from 'site/theme/template/IconSet';
|
||||
import IconSet from '../../site/component/IconSet';
|
||||
const icons1 = ['step-backward', 'step-forward', 'fast-backward', 'fast-forward', 'shrink', 'arrow-salt', 'down', 'up', 'left', 'right', 'caret-down', 'caret-up', 'caret-left', 'caret-right', 'caret-circle-right', 'caret-circle-left', 'caret-circle-o-right', 'caret-circle-o-left', 'circle-right', 'circle-left', 'circle-o-right', 'circle-o-left', 'double-right', 'double-left', 'verticle-right', 'verticle-left', 'forward', 'backward', 'rollback', 'enter', 'retweet', 'swap', 'swap-left', 'swap-right', 'arrow-right', 'arrow-up', 'arrow-down', 'arrow-left', 'play-circle', 'play-circle-o', 'circle-up', 'circle-down', 'circle-o-up', 'circle-o-down', 'caret-circle-o-up', 'caret-circle-o-down', 'caret-circle-up', 'caret-circle-down'];
|
||||
|
||||
ReactDOM.render(<IconSet className="icons" icons={icons1} key="icons1" />, mountNode);
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
order: 3
|
||||
title: 小数
|
||||
- order: 3
|
||||
- title: 小数
|
||||
---
|
||||
|
||||
和原生的数字输入框一样,value 的精度由 step 的小数位数决定。
|
||||
|
@ -9,6 +9,7 @@ title: 所有组件
|
||||
import { LocaleProvider, Pagination, DatePicker, TimePicker, Calendar,
|
||||
Popconfirm, Table, Modal, Button, Select, Transfer, Radio } from 'antd';
|
||||
import enUS from 'antd/lib/locale-provider/en_US';
|
||||
import ruRU from 'antd/lib/locale-provider/ru_RU';
|
||||
const Option = Select.Option;
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
@ -109,6 +110,7 @@ const App = React.createClass({
|
||||
<span style={{ marginRight: 16 }}>Change locale of components: </span>
|
||||
<Radio.Group defaultValue={enUS} onChange={this.changeLocale}>
|
||||
<Radio.Button key="en" value={enUS}>English</Radio.Button>
|
||||
<Radio.Button key="ru" value={ruRU}>русский язык</Radio.Button>
|
||||
<Radio.Button key="cn">中文</Radio.Button>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
|
@ -157,7 +157,6 @@ ReactDOM.render(<ExtendPalettes key="palettes" />, mountNode);
|
||||
`````__react
|
||||
const Values = require('values.js');
|
||||
const CopyToClipboard = require('react-copy-to-clipboard');
|
||||
const antd = require('antd');
|
||||
const Button = antd.Button;
|
||||
const InputNumber = antd.InputNumber;
|
||||
const Slider = antd.Slider;
|
||||
|
@ -7,7 +7,7 @@ title: 可收起展开的侧边导航
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb, Icon } from 'antd';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
|
||||
const AsideCollapse = React.createClass({
|
||||
|
@ -9,7 +9,7 @@ title: 侧边导航
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb, Icon } from 'antd';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -9,7 +9,7 @@ title: 吊顶规范
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb } from 'antd';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
|
||||
ReactDOM.render(
|
||||
<BrowserDemo>
|
||||
|
@ -7,7 +7,7 @@ title: 顶部导航 + 侧边栏
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb, Icon } from 'antd';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
|
||||
ReactDOM.render(
|
||||
|
@ -11,7 +11,7 @@ title: 顶部导航
|
||||
|
||||
````jsx
|
||||
import { Menu, Breadcrumb } from 'antd';
|
||||
import BrowserDemo from 'site/theme/template/BrowserDemo';
|
||||
import BrowserDemo from 'site/component/BrowserDemo';
|
||||
|
||||
ReactDOM.render(
|
||||
<BrowserDemo>
|
||||
|
@ -11,7 +11,6 @@ english: Motion
|
||||
|
||||
`````__react
|
||||
const cssAnimation = require('css-animation');
|
||||
const antd = require('antd');
|
||||
const Select = antd.Select;
|
||||
const Option = Select.Option;
|
||||
const OptGroup = Select.OptGroup;
|
||||
|
@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Ant Design - 一个 UI 设计语言</title>
|
||||
<link rel="icon" href="https://t.alipayobjects.com/images/T1QUBfXo4fXXXXXXXX.png" type="image/x-icon">
|
||||
<link rel="stylesheet" type="text/css" href="{{ root }}index.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="./index.css"/>
|
||||
<!--[if lt IE 10]>
|
||||
<script src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,es5-shim/4.1.14/es5-shim.min.js,es5-shim/4.1.14/es5-sham.min.js,html5shiv/3.7.2/html5shiv.min.js,media-match/2.0.2/media.match.min.js"></script>
|
||||
<![endif]-->
|
||||
@ -30,7 +30,6 @@
|
||||
return '<span class="' + className + '">' + letter + '</span>';
|
||||
}).join('');
|
||||
</script>
|
||||
<script src="{{ root }}common.js"></script>
|
||||
<script src="{{ root }}index.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -76,10 +76,6 @@
|
||||
"babel-eslint": "^6.0.2",
|
||||
"babel-jest": "^12.0.2",
|
||||
"babel-plugin-antd": "^0.4.0",
|
||||
"bisheng": "^0.5.0",
|
||||
"bisheng-plugin-description": "^0.1.1",
|
||||
"bisheng-plugin-react": "^0.1.0",
|
||||
"bisheng-plugin-toc": "0.2.0",
|
||||
"dom-scroll-into-view": "^1.1.0",
|
||||
"enquire.js": "^2.1.1",
|
||||
"es6-shim": "^0.35.0",
|
||||
@ -108,7 +104,6 @@
|
||||
"react": "^15.0.0",
|
||||
"react-addons-test-utils": "^15.0.0",
|
||||
"react-copy-to-clipboard": "^4.0.1",
|
||||
"react-document-title": "^2.0.1",
|
||||
"react-dom": "^15.0.0",
|
||||
"react-github-button": "^0.1.1",
|
||||
"react-intl": "^2.0.1",
|
||||
@ -123,7 +118,7 @@
|
||||
"dist": "antd-tools run dist",
|
||||
"compile": "antd-tools run compile",
|
||||
"clean": "antd-tools run clean",
|
||||
"start": "bisheng start -c ./site/bisheng.config.js",
|
||||
"start": "antd-tools run start",
|
||||
"site": "antd-tools run site",
|
||||
"pre-deploy": "cp CNAME _site && rsync -R components/*/demo/*.json _site",
|
||||
"deploy": "antd-tools run update-self && antd-tools run deploy",
|
||||
|
@ -1,50 +0,0 @@
|
||||
const React = require('react');
|
||||
const Link = require('react-router').Link;
|
||||
const toReactComponent = require('jsonml-to-react-component');
|
||||
const JsonML = require('jsonml.js/lib/utils');
|
||||
const VideoPlayer = require('./VideoPlayer');
|
||||
const ImagePreview = require('./ImagePreview');
|
||||
|
||||
function isHeading(node) {
|
||||
return /h[1-6]/i.test(JsonML.getTagName(node));
|
||||
}
|
||||
|
||||
module.exports = () => {
|
||||
return {
|
||||
converters: [
|
||||
[(node) => JsonML.isElement(node) && isHeading(node), (node, index) => {
|
||||
const children = JsonML.getChildren(node);
|
||||
return React.createElement(JsonML.getTagName(node), {
|
||||
key: index,
|
||||
id: children,
|
||||
...JsonML.getAttributes(node),
|
||||
}, [
|
||||
<span key="title">{children.map((child) => toReactComponent(child))}</span>,
|
||||
<a href={`#${children}`} className="anchor" key="anchor">#</a>,
|
||||
]);
|
||||
}],
|
||||
[(node) => JsonML.isElement(node) && JsonML.getTagName(node) === 'video', (node, index) =>
|
||||
<VideoPlayer video={JsonML.getAttributes(node)} key={index} />,
|
||||
],
|
||||
[(node) => JsonML.isElement(node) && JsonML.getTagName(node) === 'a' && !(
|
||||
JsonML.getAttributes(node).class ||
|
||||
(JsonML.getAttributes(node).href &&
|
||||
JsonML.getAttributes(node).href.indexOf('http') === 0) ||
|
||||
/^#/.test(JsonML.getAttributes(node).href)
|
||||
), (node, index) => {
|
||||
return <Link to={JsonML.getAttributes(node).href} key={index}>{toReactComponent(JsonML.getChildren(node)[0])}</Link>;
|
||||
}],
|
||||
[(node) => {
|
||||
return JsonML.isElement(node) &&
|
||||
JsonML.getTagName(node) === 'p' &&
|
||||
JsonML.getTagName(JsonML.getChildren(node)[0]) === 'img' &&
|
||||
/preview-img/gi.test(JsonML.getAttributes(JsonML.getChildren(node)[0]).class);
|
||||
}, (node, index) => {
|
||||
const imgs = JsonML.getChildren(node)
|
||||
.filter((img) => JsonML.isElement(img) && Object.keys(JsonML.getAttributes(img)).length > 0)
|
||||
.map((img) => JsonML.getAttributes(img));
|
||||
return <ImagePreview imgs={imgs} key={index} />;
|
||||
}],
|
||||
],
|
||||
};
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
const path = require('path');
|
||||
const processDoc = require('./process-doc');
|
||||
const processDemo = require('./process-demo');
|
||||
|
||||
module.exports = (markdownData) => {
|
||||
const isDemo = path.dirname(markdownData.meta.filename).endsWith('/demo');
|
||||
if (isDemo) {
|
||||
return processDemo(markdownData);
|
||||
}
|
||||
return processDoc(markdownData);
|
||||
};
|
@ -1,90 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const JsonML = require('jsonml.js/lib/utils');
|
||||
const pkgPath = path.join(process.cwd(), 'package.json');
|
||||
const pkgName = require(pkgPath).name;
|
||||
|
||||
const nunjucks = require('nunjucks');
|
||||
nunjucks.configure({ autoescape: false });
|
||||
|
||||
const babel = require('babel-core');
|
||||
const babelrc = {
|
||||
presets: ['es2015', 'react'].map((m) => {
|
||||
return require.resolve(`babel-preset-${m}`);
|
||||
}),
|
||||
};
|
||||
|
||||
const tmpl = fs.readFileSync(path.join(__dirname, 'template.html')).toString();
|
||||
|
||||
function isStyleTag(node) {
|
||||
return node && JsonML.getTagName(node) === 'style';
|
||||
}
|
||||
|
||||
function getCode(node) {
|
||||
return JsonML.getChildren(
|
||||
JsonML.getChildren(node)[0]
|
||||
)[0];
|
||||
}
|
||||
|
||||
module.exports = (markdownData) => {
|
||||
const meta = markdownData.meta;
|
||||
meta.id = meta.filename.replace(/\.md$/, '').replace(/\//g, '-');
|
||||
|
||||
const contentChildren = JsonML.getChildren(markdownData.content);
|
||||
const chineseIntroStart = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'h2' &&
|
||||
JsonML.getChildren(node)[0] === 'zh-CN';
|
||||
});
|
||||
const englishIntroStart = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'h2' &&
|
||||
JsonML.getChildren(node)[0] === 'en-US';
|
||||
});
|
||||
const codeIndex = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'pre' &&
|
||||
JsonML.getAttributes(node).lang === 'jsx';
|
||||
});
|
||||
if (chineseIntroStart > -1 /* equal to englishIntroStart > -1 */) {
|
||||
markdownData.content = {
|
||||
'zh-CN': contentChildren.slice(chineseIntroStart + 1, englishIntroStart),
|
||||
'en-US': contentChildren.slice(englishIntroStart + 1, codeIndex),
|
||||
};
|
||||
} else {
|
||||
markdownData.content = contentChildren.slice(0, codeIndex);
|
||||
}
|
||||
|
||||
markdownData.highlightedCode = contentChildren[codeIndex].slice(0, 2);
|
||||
const preview = [
|
||||
'pre', { lang: '__react' },
|
||||
];
|
||||
const componentsPath = path.join(process.cwd(), 'components');
|
||||
preview.push([
|
||||
'code',
|
||||
getCode(contentChildren[codeIndex])
|
||||
.replace(`${pkgName}/lib`, componentsPath),
|
||||
]);
|
||||
markdownData.preview = preview;
|
||||
|
||||
const styleNode = contentChildren.find((node) => {
|
||||
return isStyleTag(node) ||
|
||||
(JsonML.getTagName(node) === 'pre' && JsonML.getAttributes(node).lang === 'css');
|
||||
});
|
||||
if (isStyleTag(styleNode)) {
|
||||
markdownData.style = JsonML.getChildren(styleNode)[0];
|
||||
} else if (styleNode) {
|
||||
markdownData.style = getCode(styleNode);
|
||||
markdownData.highlightedStyle = JsonML.getAttributes(styleNode).highlighted;
|
||||
}
|
||||
|
||||
if (meta.iframe) {
|
||||
const html = nunjucks.renderString(tmpl, {
|
||||
id: meta.id,
|
||||
style: markdownData.style,
|
||||
script: babel.transform(getCode(markdownData.preview), babelrc).code,
|
||||
});
|
||||
const fileName = `demo-${Math.random()}.html`;
|
||||
fs.writeFile(path.join(process.cwd(), '_site', fileName), html);
|
||||
markdownData.src = path.join('/', fileName);
|
||||
}
|
||||
|
||||
return markdownData;
|
||||
};
|
@ -1,19 +0,0 @@
|
||||
const JsonML = require('jsonml.js/lib/utils');
|
||||
|
||||
module.exports = (markdownData) => {
|
||||
const contentChildren = JsonML.getChildren(markdownData.content);
|
||||
const apiStartIndex = contentChildren.findIndex((node) => {
|
||||
return JsonML.getTagName(node) === 'h2' &&
|
||||
JsonML.getChildren(node)[0] === 'API';
|
||||
});
|
||||
|
||||
if (apiStartIndex > -1) {
|
||||
const content = contentChildren.slice(0, apiStartIndex);
|
||||
markdownData.content = ['section'].concat(content);
|
||||
|
||||
const api = contentChildren.slice(apiStartIndex);
|
||||
markdownData.api = ['section'].concat(api);
|
||||
}
|
||||
|
||||
return markdownData;
|
||||
};
|
@ -1,34 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Demo</title>
|
||||
<link rel="stylesheet" href="../index.css" />
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background: none;
|
||||
}
|
||||
{{ style }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="{{ id }}" class="code-box-demo"></div>
|
||||
<script>
|
||||
function require(module) {
|
||||
if (module === 'react-router') {
|
||||
return window.ReactRouter;
|
||||
}
|
||||
return window.parent[module];
|
||||
}
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
var mountNode = document.getElementById('{{ id }}');
|
||||
</script>
|
||||
<script src="https://npmcdn.com/react-router/umd/ReactRouter.min.js"></script>
|
||||
<script>
|
||||
{{ script }}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,34 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
source: [
|
||||
'./components',
|
||||
'./docs',
|
||||
'CHANGELOG.md', // TODO: fix it in bisheng
|
||||
],
|
||||
theme: './site/theme',
|
||||
htmlTemplate: './site/theme/static/template.html',
|
||||
plugins: [
|
||||
'bisheng-plugin-description',
|
||||
'bisheng-plugin-toc?maxDepth=2',
|
||||
'bisheng-plugin-react?lang=__react',
|
||||
'./site/bisheng-plugin-antd',
|
||||
],
|
||||
webpackConfig(config) {
|
||||
config.resolve.alias = {
|
||||
antd: process.cwd(),
|
||||
site: path.join(process.cwd(), 'site'),
|
||||
};
|
||||
|
||||
config.babel.plugins.push([
|
||||
require.resolve('babel-plugin-antd'),
|
||||
{
|
||||
style: true,
|
||||
libraryName: 'antd',
|
||||
libDir: 'components',
|
||||
},
|
||||
]);
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
18
site/common/lib.js
Normal file
18
site/common/lib.js
Normal file
@ -0,0 +1,18 @@
|
||||
import './styles/highlight.less';
|
||||
import './styles/common.less';
|
||||
import './styles/markdown.less';
|
||||
import './styles/toc.less';
|
||||
import './styles/font.less';
|
||||
import './styles/resource.less';
|
||||
import './styles/clearfix.less';
|
||||
import './styles/demo.less';
|
||||
import './styles/page-nav.less';
|
||||
import './styles/footer.less';
|
||||
import './styles/preview-img.less';
|
||||
import './styles/mock-browser.less';
|
||||
import './styles/colors.less';
|
||||
import './styles/motion.less';
|
||||
import './styles/responsive.less';
|
||||
import './styles/new-version-info-modal.less';
|
||||
|
||||
import 'es6-shim';
|
14
site/common/styles/clearfix.less
Normal file
14
site/common/styles/clearfix.less
Normal file
@ -0,0 +1,14 @@
|
||||
.clearfix {
|
||||
zoom: 1;
|
||||
&:before,
|
||||
&:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
&:after {
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
font-size: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ a {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.main-container {
|
||||
.main-container {
|
||||
padding: 0 6% 120px 4%;
|
||||
margin-left: -1px;
|
||||
background: #fff;
|
@ -39,7 +39,7 @@
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.code-box:target {
|
||||
.code-box.code-box-target {
|
||||
border: 1px solid rgba(45, 183, 245, 0.7);
|
||||
box-shadow: 0 0 4px rgba(45, 183, 245, 0.5);
|
||||
}
|
||||
@ -80,7 +80,7 @@
|
||||
}
|
||||
|
||||
.code-box-meta h4,
|
||||
section.code-box-meta p {
|
||||
.code-box-meta p {
|
||||
margin: 0;
|
||||
width: 93%;
|
||||
}
|
||||
@ -172,10 +172,8 @@ section.code-box-meta p {
|
||||
}
|
||||
|
||||
.code-box .highlight {
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
padding: 5px;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-top: 1px dashed #e9e9e9;
|
||||
}
|
@ -99,6 +99,7 @@
|
||||
|
||||
.markdown pre code {
|
||||
border: none;
|
||||
padding: 1em 2em;
|
||||
background: #f7f7f7;
|
||||
margin: 0;
|
||||
font-size: 13px;
|
13
site/component/App.jsx
Normal file
13
site/component/App.jsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import Header from './Header';
|
||||
import Footer from './Footer';
|
||||
|
||||
export default function App(props) {
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<Header {...props} />
|
||||
{props.children}
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
90
site/component/Article/index.jsx
Normal file
90
site/component/Article/index.jsx
Normal file
@ -0,0 +1,90 @@
|
||||
import React, { Children, cloneElement } from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import * as utils from '../utils';
|
||||
import { getTagName, getChildren } from 'jsonml.js/lib/utils';
|
||||
import { Timeline } from 'antd';
|
||||
|
||||
export default class Article extends React.Component {
|
||||
componentDidMount() {
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const { title, chinese, english } = this.props.content.meta;
|
||||
utils.setTitle(`${title || chinese || english} - Ant Design`);
|
||||
const links = Array.apply(null, document.querySelectorAll('.outside-link.internal'));
|
||||
if (links.length === 0) {
|
||||
return;
|
||||
}
|
||||
const checkImgUrl = 'http://alipay-rmsdeploy-dev-image.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/JdVaTbZzPxEldUi.png';
|
||||
utils.ping(checkImgUrl, status => {
|
||||
if (status === 'responded') {
|
||||
links.forEach(link => (link.style.display = 'block'));
|
||||
}
|
||||
});
|
||||
}
|
||||
getArticle(article) {
|
||||
const { content } = this.props;
|
||||
const { meta } = content;
|
||||
if (!meta.timeline) {
|
||||
return article;
|
||||
}
|
||||
const timelineItems = [];
|
||||
let temp = [];
|
||||
Children.forEach(article.props.children, (child, i) => {
|
||||
if (child.type === 'h2' && temp.length > 0) {
|
||||
timelineItems.push(<Timeline.Item key={i}>{temp}</Timeline.Item>);
|
||||
temp = [];
|
||||
}
|
||||
temp.push(child);
|
||||
});
|
||||
return cloneElement(article, {
|
||||
children: <Timeline>{timelineItems}</Timeline>,
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const { content, location } = this.props;
|
||||
const jumper = content.description.filter((node) => {
|
||||
return getTagName(node) === 'h2';
|
||||
}).map((node) => {
|
||||
return (
|
||||
<li key={getChildren(node)[0]}>
|
||||
<Link to={{ pathname: location.pathname, query: { scrollTo: getChildren(node)[0] } }}>
|
||||
{utils.jsonmlToComponent(location.pathname, getChildren(node)[0])}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
const { meta, intro, description } = content;
|
||||
|
||||
return (
|
||||
<article className="markdown">
|
||||
<h1>
|
||||
{meta.title || meta.english} {meta.subtitle || meta.chinese}
|
||||
{
|
||||
!meta.subtitle ? null :
|
||||
<span className="subtitle">{meta.subtitle}</span>
|
||||
}
|
||||
</h1>
|
||||
{
|
||||
!intro ? null :
|
||||
utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', { className: 'markdown' }].concat(intro)
|
||||
)
|
||||
}
|
||||
{
|
||||
(jumper.length > 0 && meta.toc !== false) ?
|
||||
<section className="toc"><ul>{jumper}</ul></section> :
|
||||
null
|
||||
}
|
||||
{
|
||||
this.getArticle(utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', { className: 'markdown' }].concat(description)
|
||||
))
|
||||
}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
}
|
131
site/component/ComponentDoc/index.jsx
Normal file
131
site/component/ComponentDoc/index.jsx
Normal file
@ -0,0 +1,131 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import { Row, Col, Icon, Affix } from 'antd';
|
||||
import Demo from '../Demo';
|
||||
import * as utils from '../utils';
|
||||
import demosList from '../../../_data/demos-list';
|
||||
|
||||
export default class ComponentDoc extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
expandAll: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const { title, subtitle, chinese, english } = this.props.doc.meta;
|
||||
utils.setTitle(`${subtitle || chinese || ''} ${title || english} - Ant Design`);
|
||||
}
|
||||
|
||||
handleExpandToggle = () => {
|
||||
this.setState({
|
||||
expandAll: !this.state.expandAll,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { doc, location } = this.props;
|
||||
const scrollTo = location.query.scrollTo;
|
||||
const { description, meta } = doc;
|
||||
const locale = this.context.intl.locale;
|
||||
const demos = (demosList[meta.fileName.replace(`.${locale}`, '')] || [])
|
||||
.filter((demoData) => !demoData.meta.hidden);
|
||||
const expand = this.state.expandAll;
|
||||
|
||||
const isSingleCol = meta.cols === 1;
|
||||
const leftChildren = [];
|
||||
const rightChildren = [];
|
||||
demos.sort((a, b) => {
|
||||
return parseInt(a.meta.order, 10) - parseInt(b.meta.order, 10);
|
||||
}).forEach((demoData, index) => {
|
||||
if (index % 2 === 0 || isSingleCol) {
|
||||
leftChildren.push(
|
||||
<Demo {...demoData} className={scrollTo === demoData.id ? 'code-box-target' : ''}
|
||||
key={index}
|
||||
expand={expand} pathname={location.pathname} />
|
||||
);
|
||||
} else {
|
||||
rightChildren.push(
|
||||
<Demo {...demoData} className={scrollTo === demoData.id ? 'code-box-target' : ''}
|
||||
key={index}
|
||||
expand={expand} pathname={location.pathname} />
|
||||
);
|
||||
}
|
||||
});
|
||||
const expandTriggerClass = classNames({
|
||||
'code-box-expand-trigger': true,
|
||||
'code-box-expand-trigger-active': expand,
|
||||
});
|
||||
|
||||
const jumper = demos.map((demo) => {
|
||||
const title = demo.meta.title;
|
||||
const localizeTitle = typeof title === 'object' ?
|
||||
title[locale] : title;
|
||||
return (
|
||||
<li key={demo.id}>
|
||||
<Link className={demo.id === scrollTo ? 'current' : ''}
|
||||
to={{ pathname: location.pathname, query: { scrollTo: `${demo.id}` } }}>
|
||||
{localizeTitle}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<article>
|
||||
<Affix className="toc-affix" offsetTop={16}>
|
||||
<ul className="toc demos-anchor">
|
||||
{jumper}
|
||||
</ul>
|
||||
</Affix>
|
||||
<section className="markdown">
|
||||
<h1>{meta.title || meta.english} {meta.subtitle || meta.chinese}</h1>
|
||||
{
|
||||
utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', { className: 'markdown' }]
|
||||
.concat(description)
|
||||
)
|
||||
}
|
||||
<h2>
|
||||
代码演示
|
||||
<Icon type="appstore" className={expandTriggerClass}
|
||||
title="展开全部代码" onClick={this.handleExpandToggle} />
|
||||
</h2>
|
||||
</section>
|
||||
<Row gutter={16}>
|
||||
<Col span={isSingleCol ? '24' : '12'}
|
||||
className={isSingleCol ?
|
||||
'code-boxes-col-1-1' :
|
||||
'code-boxes-col-2-1'
|
||||
}
|
||||
>
|
||||
{leftChildren}
|
||||
</Col>
|
||||
{
|
||||
isSingleCol ? null :
|
||||
<Col className="code-boxes-col-2-1" span="12">{rightChildren}</Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
utils.jsonmlToComponent(
|
||||
location.pathname,
|
||||
['section', {
|
||||
className: 'markdown api-container',
|
||||
}].concat(doc.api || [])
|
||||
)
|
||||
}
|
||||
</article>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import * as utils from '../utils';
|
||||
|
||||
const isLocal = location.port;
|
||||
|
||||
export default class Demo extends React.Component {
|
||||
static contextTypes = {
|
||||
@ -28,40 +31,27 @@ export default class Demo extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const {
|
||||
meta,
|
||||
src,
|
||||
content,
|
||||
preview,
|
||||
highlightedCode,
|
||||
style,
|
||||
highlightedStyle,
|
||||
} = props;
|
||||
|
||||
const { id, className, meta, intro, preview, style, src,
|
||||
highlightedCode, highlightedStyle, pathname } = this.props;
|
||||
const codeExpand = this.state.codeExpand;
|
||||
const codeBoxClass = classNames({
|
||||
'code-box': true,
|
||||
[className]: className,
|
||||
expand: codeExpand,
|
||||
});
|
||||
|
||||
const locale = this.context.intl.locale;
|
||||
const localizedTitle = meta.title[locale] || meta.title;
|
||||
const localizeIntro = content[locale] || content;
|
||||
const introChildren = props.utils
|
||||
.toReactComponent(['div'].concat(localizeIntro));
|
||||
|
||||
const highlightClass = classNames({
|
||||
'highlight-wrapper': true,
|
||||
'highlight-wrapper-expand': codeExpand,
|
||||
});
|
||||
const localizeIntro = intro[locale] || intro;
|
||||
const introChildren = utils.jsonmlToComponent(pathname, ['div'].concat(localizeIntro));
|
||||
const localizedTitle = typeof meta.title === 'object' ?
|
||||
meta.title[locale] : meta.title;
|
||||
return (
|
||||
<section className={codeBoxClass} id={meta.id}>
|
||||
<section className={codeBoxClass} id={id}>
|
||||
<section className="code-box-demo">
|
||||
{
|
||||
meta.iframe ?
|
||||
<iframe src={src} /> :
|
||||
preview(React, ReactDOM)
|
||||
<iframe src={isLocal ? src : src.replace('./_site', '')} /> :
|
||||
preview
|
||||
}
|
||||
{
|
||||
!!style ?
|
||||
@ -71,19 +61,23 @@ export default class Demo extends React.Component {
|
||||
</section>
|
||||
<section className="code-box-meta markdown">
|
||||
<div className="code-box-title">
|
||||
<a href={`#${meta.id}`}>
|
||||
<Link to={{ pathname, query: { scrollTo: id } }}>
|
||||
{localizedTitle}
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
{introChildren}
|
||||
<span className="collapse anticon anticon-circle-o-right"
|
||||
onClick={this.handleCodeExapnd}
|
||||
unselectable="none" />
|
||||
</section>
|
||||
<section className={highlightClass}
|
||||
<section className={`highlight-wrapper ${codeExpand ? 'highlight-wrapper-expand' : ''}`}
|
||||
key="code">
|
||||
<div className="highlight">
|
||||
{props.utils.toReactComponent(highlightedCode)}
|
||||
<pre>
|
||||
<code className="javascript" dangerouslySetInnerHTML={{
|
||||
__html: highlightedCode,
|
||||
}} />
|
||||
</pre>
|
||||
</div>
|
||||
{
|
||||
highlightedStyle ?
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Select, Modal } from 'antd';
|
||||
import { version as antdVersion } from 'antd/package.json';
|
||||
import { docVersions } from '../../';
|
||||
import { version as antdVersion } from '../../../package.json';
|
||||
import { docVersions } from '../../website.config';
|
||||
const Option = Select.Option;
|
||||
|
||||
function isLocalStorageNameSupported() {
|
@ -7,6 +7,9 @@ import classNames from 'classnames';
|
||||
import { Select, Menu, Row, Col, Icon, Button } from 'antd';
|
||||
const Option = Select.Option;
|
||||
|
||||
import './index.less';
|
||||
|
||||
import componentsList from '../../../_data/react-components';
|
||||
export default class Header extends React.Component {
|
||||
static contextTypes = {
|
||||
router: React.PropTypes.object.isRequired,
|
||||
@ -84,34 +87,22 @@ export default class Header extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { routes, data } = this.props;
|
||||
const route = routes[0].path.replace(/^\//, '');
|
||||
let activeMenuItem = route.slice(0, route.indexOf(':') - 1) || 'home';
|
||||
const routes = this.props.routes;
|
||||
let activeMenuItem = routes[1].path || 'home';
|
||||
activeMenuItem = activeMenuItem === 'components' ? 'docs/react' : activeMenuItem;
|
||||
|
||||
const locale = this.context.intl.locale;
|
||||
const componentsList = Object.keys(data.components)
|
||||
.map((component) => {
|
||||
const index = data.components[component].index;
|
||||
if (index.meta) {
|
||||
return index;
|
||||
}
|
||||
return index[locale];
|
||||
})
|
||||
.filter(item => item);
|
||||
|
||||
const options = Object.keys(componentsList)
|
||||
.map((key) => {
|
||||
const value = componentsList[key];
|
||||
return value.localized ? value[locale] : value;
|
||||
})
|
||||
.filter(({ meta }) => {
|
||||
return /^components/.test(meta.filename);
|
||||
return /^component/.test(meta.fileName);
|
||||
})
|
||||
.map(({ meta }) => {
|
||||
const pathSnippet = meta.filename.split('/')[1];
|
||||
const pathSnippet = meta.fileName.split('/')[1];
|
||||
const url = `/components/${pathSnippet}`;
|
||||
|
||||
return (
|
||||
<Option value={url} key={url} data-label={`${(meta.title || meta.english).toLowerCase()} ${meta.subtitle || meta.chinese}`}>
|
||||
<strong>{meta.title || meta.english}</strong>
|
||||
@ -169,27 +160,27 @@ export default class Header extends React.Component {
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="docs/practice">
|
||||
<Link to="/docs/practice/cases">
|
||||
<Link to="/docs/practice">
|
||||
<FormattedMessage id="app.header.menu.practice" />
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="docs/pattern">
|
||||
<Link to="/docs/pattern/navigation">
|
||||
<Link to="/docs/pattern">
|
||||
<FormattedMessage id="app.header.menu.pattern" />
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="docs/react">
|
||||
<Link to="/docs/react/introduce">
|
||||
<Link to="/docs/react">
|
||||
<FormattedMessage id="app.header.menu.react" />
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="docs/spec">
|
||||
<Link to="/docs/spec/introduce">
|
||||
<Link to="/docs/spec">
|
||||
<FormattedMessage id="app.header.menu.spec" />
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="docs/resource">
|
||||
<Link to="/docs/resource/download">
|
||||
<Link to="/docs/resource">
|
||||
<FormattedMessage id="app.header.menu.resource" />
|
||||
</Link>
|
||||
</Menu.Item>
|
@ -90,22 +90,22 @@
|
||||
|
||||
.component-select {
|
||||
&.ant-select-dropdown {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
font-size: 14px;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
font-size: 14px;
|
||||
}
|
||||
.ant-select-dropdown-menu {
|
||||
max-height: 200px;
|
||||
max-height: 200px;
|
||||
}
|
||||
.ant-select-dropdown-menu-item {
|
||||
border-radius: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.ant-component-decs {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
color: #aaa;
|
||||
right: 16px;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
color: #aaa;
|
||||
right: 16px;
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ export default function Page3() {
|
||||
<h2 key="h2">丰富的基础组件</h2>
|
||||
<p key="p" style={{ maxWidth: 280 }}>丰富、灵活、实用的基础组件,为业务产品提供强有力的设计支持。</p>
|
||||
<div key="button">
|
||||
<Link to="/docs/react/introduce">
|
||||
<Link to="/docs/react">
|
||||
<Button type="primary" size="large">
|
||||
了解更多
|
||||
<Icon type="right" />
|
@ -1,14 +1,21 @@
|
||||
import React from 'react';
|
||||
import DocumentTitle from 'react-document-title';
|
||||
import Layout from '../Layout';
|
||||
import Link from './Link';
|
||||
import Banner from './Banner';
|
||||
import Page1 from './Page1';
|
||||
import Page2 from './Page2';
|
||||
import Page3 from './Page3';
|
||||
import Page4 from './Page4';
|
||||
import './index.less';
|
||||
|
||||
import * as utils from '../utils';
|
||||
|
||||
export default class Home extends React.Component {
|
||||
componentDidMount() {
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
utils.setTitle('Ant Design - 一个 UI 设计语言');
|
||||
}
|
||||
// To store style which is only for Home and has conflicts with others.
|
||||
getStyle() {
|
||||
return `
|
||||
@ -87,19 +94,15 @@ export default class Home extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<DocumentTitle title="Ant Design - 一个 UI 设计语言">
|
||||
<Layout {...this.props}>
|
||||
<div className="main-wrapper">
|
||||
<Link />
|
||||
<Banner />
|
||||
<Page1 />
|
||||
<Page2 />
|
||||
<Page3 />
|
||||
<Page4 />
|
||||
<style dangerouslySetInnerHTML={{ __html: this.getStyle() }} />
|
||||
</div>
|
||||
</Layout>
|
||||
</DocumentTitle>
|
||||
<div className="main-wrapper">
|
||||
<Link />
|
||||
<Banner />
|
||||
<Page1 />
|
||||
<Page2 />
|
||||
<Page3 />
|
||||
<Page4 />
|
||||
<style dangerouslySetInnerHTML={{ __html: this.getStyle() }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -2,45 +2,57 @@ import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import scrollIntoView from 'dom-scroll-into-view';
|
||||
import { Row, Col, Menu } from 'antd';
|
||||
import Article from './Article';
|
||||
import ComponentDoc from './ComponentDoc';
|
||||
import * as utils from '../utils';
|
||||
import config from '../../';
|
||||
import config from '../../website.config';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
|
||||
export default class MainContent extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
scrollIntoView(document.body, document, { alignWithTop: true });
|
||||
this.scrollToAnchor(this.props);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
this.scrollToAnchor(nextProps);
|
||||
|
||||
const pathname = this.props.location.pathname;
|
||||
return pathname !== nextProps.location.pathname ||
|
||||
/^\/components\//i.test(pathname);
|
||||
}
|
||||
|
||||
scrollToAnchor(props) {
|
||||
const scrollTo = props.location.query.scrollTo;
|
||||
if (scrollTo !== undefined) {
|
||||
const target = document.getElementById(scrollTo);
|
||||
|
||||
if (target !== null) {
|
||||
scrollIntoView(
|
||||
target,
|
||||
document,
|
||||
{ alignWithTop: true, onlyScrollIfNeeded: false }
|
||||
);
|
||||
}
|
||||
} else {
|
||||
scrollIntoView(document.body, document, { alignWithTop: true });
|
||||
}
|
||||
}
|
||||
|
||||
getActiveMenuItem(props) {
|
||||
return props.params.children;
|
||||
}
|
||||
|
||||
fileNameToPath(filename) {
|
||||
const snippets = filename.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '').split('/');
|
||||
fileNameToPath(fileName) {
|
||||
const snippets = fileName.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '').split('/');
|
||||
return snippets[snippets.length - 1];
|
||||
}
|
||||
|
||||
generateMenuItem(isTop, item) {
|
||||
const key = this.fileNameToPath(item.filename);
|
||||
const key = this.fileNameToPath(item.fileName);
|
||||
const text = isTop ?
|
||||
item.title || item.chinese || item.english : [
|
||||
<span key="english">{item.title || item.english}</span>,
|
||||
<span className="chinese" key="chinese">{item.subtitle || item.chinese}</span>,
|
||||
];
|
||||
const disabled = item.disabled;
|
||||
const url = item.filename.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '');
|
||||
const url = item.fileName.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '');
|
||||
const child = !item.link ?
|
||||
<Link to={url} disabled={disabled}>
|
||||
{text}
|
||||
@ -81,27 +93,9 @@ export default class MainContent extends React.Component {
|
||||
return [...topLevel, ...itemGroups];
|
||||
}
|
||||
|
||||
getModuleData() {
|
||||
const props = this.props;
|
||||
|
||||
let moduleData;
|
||||
if (/(docs\/react\/)|(components\/)|(CHANGELOG)/i.test(props.location.pathname)) {
|
||||
moduleData = {
|
||||
...props.data.docs.react,
|
||||
...props.data.components,
|
||||
CHANGELOG: props.data.CHANGELOG,
|
||||
};
|
||||
} else {
|
||||
moduleData = props.utils.get(props.data, props.location.pathname.split('/').slice(0, 2));
|
||||
}
|
||||
|
||||
return moduleData;
|
||||
}
|
||||
|
||||
getMenuItems() {
|
||||
const moduleData = this.getModuleData();
|
||||
|
||||
const menuItems = utils.getMenuItems(moduleData, this.context.intl.locale);
|
||||
const props = this.props;
|
||||
const menuItems = props.menuItems;
|
||||
const topLevel = this.generateSubMenuItems(menuItems.topLevel);
|
||||
const subMenu = Object.keys(menuItems).filter(this.isNotTopLevel)
|
||||
.sort((a, b) => {
|
||||
@ -146,31 +140,22 @@ export default class MainContent extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const activeMenuItem = this.getActiveMenuItem(props);
|
||||
const activeMenuItem = this.getActiveMenuItem(this.props);
|
||||
const menuItems = this.getMenuItems();
|
||||
const { prev, next } = this.getFooterNav(menuItems, activeMenuItem);
|
||||
|
||||
const locale = this.context.intl.locale;
|
||||
const moduleData = this.getModuleData();
|
||||
const pageData = props.pageData.index || props.pageData;
|
||||
const localizedPageData = pageData[locale] || pageData;
|
||||
return (
|
||||
<div className="main-wrapper">
|
||||
<Row>
|
||||
<Col lg={4} md={6} sm={24} xs={24}>
|
||||
<Menu className="aside-container" mode="inline"
|
||||
defaultOpenKeys={Object.keys(utils.getMenuItems(moduleData, locale))}
|
||||
defaultOpenKeys={Object.keys(this.props.menuItems)}
|
||||
selectedKeys={[activeMenuItem]}>
|
||||
{menuItems}
|
||||
</Menu>
|
||||
</Col>
|
||||
<Col lg={20} md={18} sm={24} xs={24} className="main-container">
|
||||
{
|
||||
props.pageData.demo ?
|
||||
<ComponentDoc {...props} doc={localizedPageData} demos={props.pageData.demo} /> :
|
||||
<Article {...props} content={localizedPageData} />
|
||||
}
|
||||
{this.props.children}
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import './index.less';
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
80
site/component/utils.js
Normal file
80
site/component/utils.js
Normal file
@ -0,0 +1,80 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Link } from 'react-router';
|
||||
import { getTagName, getAttributes, getChildren, isElement } from 'jsonml.js/lib/utils';
|
||||
import toReactComponent from 'jsonml-to-react-component';
|
||||
import VideoPlayer from './VideoPlayer';
|
||||
import ImagePreview from './ImagePreview';
|
||||
|
||||
function isHeading(type) {
|
||||
return /h[1-6]/i.test(type);
|
||||
}
|
||||
|
||||
export function jsonmlToComponent(pathname, jsonml) {
|
||||
return toReactComponent(jsonml, [
|
||||
[(node) => React.isValidElement(node), (node, index) => {
|
||||
return React.cloneElement(node, { key: index });
|
||||
}],
|
||||
[(node) => typeof node === 'function', (node, index) => {
|
||||
return React.cloneElement(node(React, ReactDOM), { key: index });
|
||||
}],
|
||||
[(node) => isHeading(getTagName(node)), (node, index) => {
|
||||
const children = getChildren(node);
|
||||
return React.createElement(getTagName(node), {
|
||||
key: index,
|
||||
id: children,
|
||||
...getAttributes(node),
|
||||
}, [
|
||||
<span key="title">{children.map((child) => toReactComponent(child))}</span>,
|
||||
<Link to={{ pathname, query: { scrollTo: children } }} className="anchor" key="anchor">#</Link>,
|
||||
]);
|
||||
}],
|
||||
[(node) => getTagName(node) === 'pre' && getAttributes(node).highlighted, (node, index) => {
|
||||
return React.createElement('pre', { key: index, lang: getAttributes(node).lang }, React.createElement(
|
||||
'code',
|
||||
{ dangerouslySetInnerHTML: { __html: getChildren(getChildren(node)[0])[0] } }
|
||||
));
|
||||
}],
|
||||
[(node) => getTagName(node) === 'video', (node, index) =>
|
||||
<VideoPlayer video={getAttributes(node)} key={index} />,
|
||||
],
|
||||
[(node) => isElement(node) && getTagName(node) === 'a' && !(
|
||||
getAttributes(node).class ||
|
||||
(getAttributes(node).href &&
|
||||
getAttributes(node).href.indexOf('http') === 0)
|
||||
), (node, index) => {
|
||||
return <Link to={getAttributes(node).href} key={index}>{toReactComponent(getChildren(node)[0])}</Link>;
|
||||
}],
|
||||
[(node) => {
|
||||
return isElement(node) &&
|
||||
getTagName(node) === 'p' &&
|
||||
getTagName(getChildren(node)[0]) === 'img' &&
|
||||
/preview-img/gi.test(getAttributes(getChildren(node)[0]).class);
|
||||
}, (node, index) => {
|
||||
const imgs = getChildren(node)
|
||||
.filter((img) => isElement(img) && Object.keys(getAttributes(img)).length > 0)
|
||||
.map((img) => getAttributes(img));
|
||||
return <ImagePreview imgs={imgs} key={index} />;
|
||||
}],
|
||||
]);
|
||||
}
|
||||
|
||||
export function setTitle(title) {
|
||||
document.title = title;
|
||||
}
|
||||
|
||||
export function ping(url, callback) {
|
||||
const img = new Image();
|
||||
let done;
|
||||
const finish = (status) => {
|
||||
if (!done) {
|
||||
done = true;
|
||||
img.src = '';
|
||||
callback(status);
|
||||
}
|
||||
};
|
||||
img.onload = () => finish('responded');
|
||||
img.onerror = () => finish('error');
|
||||
img.src = url;
|
||||
setTimeout(() => finish('timeout'), 1500);
|
||||
}
|
131
site/entry/index.jsx
Normal file
131
site/entry/index.jsx
Normal file
@ -0,0 +1,131 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { addLocaleData, IntlProvider } from 'react-intl';
|
||||
import { Router, Route, IndexRoute, Redirect, useRouterHistory } from 'react-router';
|
||||
import antd from '../../index.js';
|
||||
import * as utils from './utils';
|
||||
import '../common/lib';
|
||||
import App from '../component/App';
|
||||
import Home from '../component/Home/index';
|
||||
import NotFound from '../component/NotFound/index';
|
||||
import practice from '../../_data/practice';
|
||||
import pattern from '../../_data/pattern';
|
||||
import reactComponents from '../../_data/react-components';
|
||||
import spec from '../../_data/spec';
|
||||
import resource from '../../_data/resource';
|
||||
import config from '../website.config';
|
||||
import enLocale from './en-US.js';
|
||||
import cnLocale from './zh-CN.js';
|
||||
import { createHashHistory } from 'history';
|
||||
|
||||
// useRouterHistory creates a composable higher-order function
|
||||
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||
|
||||
// TODO: pack dependencies with atool build
|
||||
// Expose React, ReactDOM
|
||||
window.react = React;
|
||||
window['react-dom'] = ReactDOM;
|
||||
window.antd = antd;
|
||||
|
||||
const ReactComponents = utils.generateContainer(reactComponents);
|
||||
const Practice = utils.generateContainer(practice);
|
||||
const Pattern = utils.generateContainer(pattern);
|
||||
const Spec = utils.generateContainer(spec);
|
||||
const Resource = utils.generateContainer(resource);
|
||||
const redirects = Object.keys(config.redirects).map((from, index) => {
|
||||
return <Redirect from={from} to={config.redirects[from]} key={index} />;
|
||||
});
|
||||
|
||||
// Enable Google Analytics
|
||||
if (!location.port) {
|
||||
/* eslint-disable */
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-72788897-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
appHistory.listen((loc) => {
|
||||
ga('send', 'pageview', loc.pathname + loc.search);
|
||||
});
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
// Polyfill
|
||||
const areIntlLocalesSupported = require('intl-locales-supported');
|
||||
const localesMyAppSupports = ['zh-CN', 'en-US'];
|
||||
|
||||
if (global.Intl) {
|
||||
// Determine if the built-in `Intl` has the locale data we need.
|
||||
if (!areIntlLocalesSupported(localesMyAppSupports)) {
|
||||
// `Intl` exists, but it doesn't have the data we need, so load the
|
||||
// polyfill and patch the constructors we need with the polyfill's.
|
||||
/* eslint-disable global-require */
|
||||
const IntlPolyfill = require('intl');
|
||||
/* eslint-enable global-require */
|
||||
Intl.NumberFormat = IntlPolyfill.NumberFormat;
|
||||
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
|
||||
}
|
||||
} else {
|
||||
// No `Intl`, so use and load the polyfill.
|
||||
/* eslint-disable global-require */
|
||||
global.Intl = require('intl');
|
||||
/* eslint-enable global-require */
|
||||
}
|
||||
|
||||
|
||||
const isZhCN = (typeof localStorage !== 'undefined' && localStorage.getItem('locale') !== 'en-US');
|
||||
// (typeof localStorage !== 'undefined' && localStorage.getItem('locale') === 'zh-CN') ||
|
||||
// (navigator.language === 'zh-CN');
|
||||
const appLocale = isZhCN ? cnLocale : enLocale;
|
||||
addLocaleData(appLocale.data);
|
||||
|
||||
ReactDOM.render(
|
||||
<IntlProvider locale={appLocale.locale} messages={appLocale.messages}>
|
||||
<Router history={appHistory}>
|
||||
<Route path="/" component={App}>
|
||||
<IndexRoute component={Home} />
|
||||
<Route path="components" component={ReactComponents}>
|
||||
{utils.generateIndex(reactComponents)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(reactComponents)}
|
||||
component={utils.getChildrenWrapper(reactComponents)} />
|
||||
</Route>
|
||||
{redirects}
|
||||
<Route path="docs/react" component={ReactComponents}>
|
||||
{utils.generateIndex(reactComponents)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(reactComponents)}
|
||||
component={utils.getChildrenWrapper(reactComponents)} />
|
||||
</Route>
|
||||
<Route path="docs/practice" component={Practice}>
|
||||
{utils.generateIndex(practice)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(practice)}
|
||||
component={utils.getChildrenWrapper(practice)} />
|
||||
</Route>
|
||||
<Route path="docs/pattern" component={Pattern}>
|
||||
{utils.generateIndex(pattern)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(pattern)}
|
||||
component={utils.getChildrenWrapper(pattern)} />
|
||||
</Route>
|
||||
<Route path="docs/spec" component={Spec}>
|
||||
{utils.generateIndex(spec)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(spec)}
|
||||
component={utils.getChildrenWrapper(spec)} />
|
||||
</Route>
|
||||
<Route path="docs/resource" component={Resource}>
|
||||
{utils.generateIndex(resource)}
|
||||
<Route path=":children"
|
||||
onEnter={utils.getEnterHandler(resource)}
|
||||
component={utils.getChildrenWrapper(resource)} />
|
||||
</Route>
|
||||
<Route path="*" component={NotFound} />
|
||||
</Route>
|
||||
</Router>
|
||||
</IntlProvider>
|
||||
, document.getElementById('react-content')
|
||||
);
|
120
site/entry/utils.js
Normal file
120
site/entry/utils.js
Normal file
@ -0,0 +1,120 @@
|
||||
/* eslint-disable react/prefer-stateless-function, react/no-multi-comp */
|
||||
import React from 'react';
|
||||
import { IndexRedirect } from 'react-router';
|
||||
import MainContent from '../component/MainContent';
|
||||
import Article from '../component/Article';
|
||||
import ComponentDoc from '../component/ComponentDoc';
|
||||
import demosList from '../../_data/demos-list';
|
||||
import { redirects } from '../website.config';
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept('../../_data/demos-list', () => {});
|
||||
}
|
||||
|
||||
function fileNameToPath(fileName) {
|
||||
const snippets = fileName
|
||||
.replace(/(\/index)?((\.zh-CN)|(\.en-US))?\.md$/i, '').split('/');
|
||||
return snippets[snippets.length - 1];
|
||||
}
|
||||
|
||||
function getMenuItems(data, locale) {
|
||||
const menuMeta = Object.keys(data)
|
||||
.map((key) => data[key])
|
||||
.map((file) => {
|
||||
if (file.localized) {
|
||||
return file[locale].meta;
|
||||
}
|
||||
return file.meta;
|
||||
});
|
||||
|
||||
const menuItems = {};
|
||||
menuMeta.sort((a, b) => {
|
||||
return parseInt(a.order, 10) - parseInt(b.order, 10);
|
||||
}).forEach((meta) => {
|
||||
const category = meta.category || 'topLevel';
|
||||
if (!menuItems[category]) {
|
||||
menuItems[category] = {};
|
||||
}
|
||||
|
||||
const type = meta.type || 'topLevel';
|
||||
if (!menuItems[category][type]) {
|
||||
menuItems[category][type] = [];
|
||||
}
|
||||
|
||||
menuItems[category][type].push(meta);
|
||||
});
|
||||
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
export function generateContainer(data) {
|
||||
return class containerWrapper extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const locale = this.context.intl.locale;
|
||||
const menuItems = getMenuItems(data, locale);
|
||||
return (
|
||||
<MainContent {...this.props} menuItems={menuItems} />
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function generateIndex(data) {
|
||||
const menuItems = getMenuItems(data, 'zh-CN'); // 以中文版配置为准
|
||||
const firstChild = menuItems.topLevel.topLevel.filter((item) => {
|
||||
return !item.disabled;
|
||||
})[0];
|
||||
return (
|
||||
<IndexRedirect key="index"
|
||||
to={fileNameToPath(firstChild.fileName)} />
|
||||
);
|
||||
}
|
||||
|
||||
const pathToFile = {};
|
||||
Object.keys(redirects).forEach((key) => pathToFile[redirects[key]] = key);
|
||||
pathToFile['docs/react/changelog'] = './CHANGELOG'; // TODO
|
||||
|
||||
function getDoc(data, props) {
|
||||
const trimedPathname = props.location.pathname.replace(/^\//, '');
|
||||
const processedPathname = pathToFile[trimedPathname] || trimedPathname;
|
||||
const doc = data[`${processedPathname}.md`] ||
|
||||
data[`${processedPathname}/index.md`];
|
||||
return doc;
|
||||
}
|
||||
|
||||
export function getChildrenWrapper(data) {
|
||||
return class childrenWrapper extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object,
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const trimedPathname = props.location.pathname.replace(/^\//, '');
|
||||
const processedPathname = pathToFile[trimedPathname] || trimedPathname;
|
||||
const rawDoc = data[`${processedPathname}.md`] ||
|
||||
data[`${processedPathname}/index.md`];
|
||||
|
||||
const locale = this.context.intl.locale;
|
||||
const doc = rawDoc.localized ? rawDoc[locale] : rawDoc;
|
||||
|
||||
const hasDemos = demosList[doc.meta.fileName.replace(`.${locale}`, '')];
|
||||
return !hasDemos ?
|
||||
<Article {...props} content={doc} /> :
|
||||
<ComponentDoc {...props} doc={doc} />;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getEnterHandler(data) {
|
||||
return function handleEnter(nextState, replace) {
|
||||
const doc = getDoc(data, nextState);
|
||||
if (!doc) {
|
||||
replace('/404');
|
||||
}
|
||||
};
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
import './common.less';
|
||||
import './header.less';
|
||||
import './footer.less';
|
||||
import './home.less';
|
||||
import './page-nav.less';
|
||||
import './markdown.less';
|
||||
import './resource.less';
|
||||
import './responsive.less';
|
||||
import './preview-img.less';
|
||||
import './toc.less';
|
||||
import './not-found.less';
|
||||
import './font.less';
|
||||
import './highlight.less';
|
||||
import './demo.less';
|
||||
import './colors.less';
|
||||
import './mock-browser.less';
|
||||
import './new-version-info-modal.less';
|
||||
import './motion.less';
|
@ -1,77 +0,0 @@
|
||||
import React, { Children, cloneElement } from 'react';
|
||||
import DocumentTitle from 'react-document-title';
|
||||
import { getChildren } from 'jsonml.js/lib/utils';
|
||||
import { Timeline } from 'antd';
|
||||
import * as utils from '../utils';
|
||||
|
||||
export default class Article extends React.Component {
|
||||
componentDidMount() {
|
||||
this.componentDidUpdate();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const links = Array.apply(null, document.querySelectorAll('.outside-link.internal'));
|
||||
if (links.length === 0) {
|
||||
return;
|
||||
}
|
||||
const checkImgUrl = 'http://alipay-rmsdeploy-dev-image.oss-cn-hangzhou-zmf.aliyuncs.com/rmsportal/JdVaTbZzPxEldUi.png';
|
||||
utils.ping(checkImgUrl, status => {
|
||||
if (status === 'responded') {
|
||||
links.forEach(link => (link.style.display = 'block'));
|
||||
}
|
||||
});
|
||||
}
|
||||
getArticle(article) {
|
||||
const { content } = this.props;
|
||||
const { meta } = content;
|
||||
if (!meta.timeline) {
|
||||
return article;
|
||||
}
|
||||
const timelineItems = [];
|
||||
let temp = [];
|
||||
Children.forEach(article.props.children, (child, i) => {
|
||||
if (child.type === 'h2' && temp.length > 0) {
|
||||
timelineItems.push(<Timeline.Item key={i}>{temp}</Timeline.Item>);
|
||||
temp = [];
|
||||
}
|
||||
temp.push(child);
|
||||
});
|
||||
return cloneElement(article, {
|
||||
children: <Timeline>{timelineItems}</Timeline>,
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const props = this.props;
|
||||
const content = props.content;
|
||||
|
||||
const { meta, description } = content;
|
||||
const { title, subtitle, chinese, english } = meta;
|
||||
return (
|
||||
<DocumentTitle title={`${title || chinese || english} - Ant Design`}>
|
||||
<article className="markdown">
|
||||
<h1>
|
||||
{title || english}
|
||||
{
|
||||
(!subtitle && !chinese) ? null :
|
||||
<span className="subtitle">{subtitle || chinese}</span>
|
||||
}
|
||||
</h1>
|
||||
{
|
||||
!description ? null :
|
||||
props.utils.toReactComponent(
|
||||
['section', { className: 'markdown' }].concat(getChildren(description))
|
||||
)
|
||||
}
|
||||
{
|
||||
!content.toc ? null :
|
||||
<section className="toc">{props.utils.toReactComponent(content.toc)}</section>
|
||||
}
|
||||
{
|
||||
this.getArticle(props.utils.toReactComponent(
|
||||
['section', { className: 'markdown' }].concat(getChildren(content.content))
|
||||
))
|
||||
}
|
||||
</article>
|
||||
</DocumentTitle>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
import React from 'react';
|
||||
import DocumentTitle from 'react-document-title';
|
||||
import classNames from 'classnames';
|
||||
import { Row, Col, Icon, Affix } from 'antd';
|
||||
import { getChildren } from 'jsonml.js/lib/utils';
|
||||
import Demo from './Demo';
|
||||
|
||||
export default class ComponentDoc extends React.Component {
|
||||
static contextTypes = {
|
||||
intl: React.PropTypes.object,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
expandAll: false,
|
||||
};
|
||||
}
|
||||
|
||||
handleExpandToggle = () => {
|
||||
this.setState({
|
||||
expandAll: !this.state.expandAll,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const props = this.props;
|
||||
const { doc, location } = props;
|
||||
const { content, meta } = doc;
|
||||
const locale = this.context.intl.locale;
|
||||
const demos = Object.keys(props.demos).map((key) => props.demos[key])
|
||||
.filter((demoData) => !demoData.meta.hidden);
|
||||
const expand = this.state.expandAll;
|
||||
|
||||
const isSingleCol = meta.cols === 1;
|
||||
const leftChildren = [];
|
||||
const rightChildren = [];
|
||||
demos.sort((a, b) => a.meta.order - b.meta.order)
|
||||
.forEach((demoData, index) => {
|
||||
if (index % 2 === 0 || isSingleCol) {
|
||||
leftChildren.push(
|
||||
<Demo {...demoData}
|
||||
key={index} utils={props.utils}
|
||||
expand={expand} pathname={location.pathname} />
|
||||
);
|
||||
} else {
|
||||
rightChildren.push(
|
||||
<Demo {...demoData}
|
||||
key={index} utils={props.utils}
|
||||
expand={expand} pathname={location.pathname} />
|
||||
);
|
||||
}
|
||||
});
|
||||
const expandTriggerClass = classNames({
|
||||
'code-box-expand-trigger': true,
|
||||
'code-box-expand-trigger-active': expand,
|
||||
});
|
||||
|
||||
const jumper = demos.map((demo) => {
|
||||
const title = demo.meta.title;
|
||||
const localizeTitle = title[locale] || title;
|
||||
return (
|
||||
<li key={demo.meta.id}>
|
||||
<a href={`#${demo.meta.id}`}>
|
||||
{localizeTitle}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
const { title, subtitle, chinese, english } = meta;
|
||||
return (
|
||||
<DocumentTitle title={`${subtitle || chinese || ''} ${title || english} - Ant Design`}>
|
||||
<article>
|
||||
<Affix className="toc-affix" offsetTop={16}>
|
||||
<ul className="toc demos-anchor">
|
||||
{jumper}
|
||||
</ul>
|
||||
</Affix>
|
||||
<section className="markdown">
|
||||
<h1>{meta.title || meta.english} {meta.subtitle || meta.chinese}</h1>
|
||||
{
|
||||
props.utils.toReactComponent(
|
||||
['section', { className: 'markdown' }]
|
||||
.concat(getChildren(content))
|
||||
)
|
||||
}
|
||||
<h2>
|
||||
代码演示
|
||||
<Icon type="appstore" className={expandTriggerClass}
|
||||
title="展开全部代码" onClick={this.handleExpandToggle} />
|
||||
</h2>
|
||||
</section>
|
||||
<Row gutter={16}>
|
||||
<Col span={isSingleCol ? '24' : '12'}
|
||||
className={isSingleCol ?
|
||||
'code-boxes-col-1-1' :
|
||||
'code-boxes-col-2-1'
|
||||
}
|
||||
>
|
||||
{leftChildren}
|
||||
</Col>
|
||||
{
|
||||
isSingleCol ? null :
|
||||
<Col className="code-boxes-col-2-1" span="12">{rightChildren}</Col>
|
||||
}
|
||||
</Row>
|
||||
{
|
||||
props.utils.toReactComponent(
|
||||
['section', {
|
||||
className: 'markdown api-container',
|
||||
}].concat(getChildren(doc.api || ['placeholder']))
|
||||
)
|
||||
}
|
||||
</article>
|
||||
</DocumentTitle>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import React from 'react';
|
||||
import Layout from '../Layout';
|
||||
import MainContent from './MainContent';
|
||||
|
||||
export default (props) => {
|
||||
return (
|
||||
<Layout {...props}>
|
||||
<MainContent {...props} />
|
||||
</Layout>
|
||||
);
|
||||
};
|
@ -1,70 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { addLocaleData, IntlProvider } from 'react-intl';
|
||||
import Header from './Header';
|
||||
import Footer from './Footer';
|
||||
import enLocale from '../../en-US.js';
|
||||
import cnLocale from '../../zh-CN.js';
|
||||
import '../../static/style';
|
||||
|
||||
// Expose to iframe
|
||||
window.react = React;
|
||||
window['react-dom'] = ReactDOM;
|
||||
window.antd = require('antd');
|
||||
|
||||
// Enable Google Analytics
|
||||
if (!location.port) {
|
||||
/* eslint-disable */
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-72788897-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
appHistory.listen((loc) => {
|
||||
ga('send', 'pageview', loc.pathname + loc.search);
|
||||
});
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
// Polyfill
|
||||
const areIntlLocalesSupported = require('intl-locales-supported');
|
||||
const localesMyAppSupports = ['zh-CN', 'en-US'];
|
||||
|
||||
if (global.Intl) {
|
||||
// Determine if the built-in `Intl` has the locale data we need.
|
||||
if (!areIntlLocalesSupported(localesMyAppSupports)) {
|
||||
// `Intl` exists, but it doesn't have the data we need, so load the
|
||||
// polyfill and patch the constructors we need with the polyfill's.
|
||||
/* eslint-disable global-require */
|
||||
const IntlPolyfill = require('intl');
|
||||
/* eslint-enable global-require */
|
||||
Intl.NumberFormat = IntlPolyfill.NumberFormat;
|
||||
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
|
||||
}
|
||||
} else {
|
||||
// No `Intl`, so use and load the polyfill.
|
||||
/* eslint-disable global-require */
|
||||
global.Intl = require('intl');
|
||||
/* eslint-enable global-require */
|
||||
}
|
||||
|
||||
const isZhCN = (typeof localStorage !== 'undefined' && localStorage.getItem('locale') !== 'en-US');
|
||||
// (typeof localStorage !== 'undefined' && localStorage.getItem('locale') === 'zh-CN') ||
|
||||
// (navigator.language === 'zh-CN');
|
||||
|
||||
const appLocale = isZhCN ? cnLocale : enLocale;
|
||||
addLocaleData(appLocale.data);
|
||||
|
||||
export default (props) => {
|
||||
return (
|
||||
<IntlProvider locale={appLocale.locale} messages={appLocale.messages}>
|
||||
<div className="page-wrapper">
|
||||
<Header {...props} />
|
||||
{props.children}
|
||||
<Footer />
|
||||
</div>
|
||||
</IntlProvider>
|
||||
);
|
||||
};
|
@ -1,46 +0,0 @@
|
||||
export function getMenuItems(data, locale) {
|
||||
const menuMeta = Object.keys(data)
|
||||
.map((key) => data[key])
|
||||
.map((item) => {
|
||||
const file = item.index || item;
|
||||
if (file.meta) {
|
||||
return file.meta;
|
||||
}
|
||||
return file[locale].meta;
|
||||
});
|
||||
|
||||
const menuItems = {};
|
||||
menuMeta.sort((a, b) => {
|
||||
return parseInt(a.order, 10) - parseInt(b.order, 10);
|
||||
}).forEach((meta) => {
|
||||
const category = meta.category || 'topLevel';
|
||||
if (!menuItems[category]) {
|
||||
menuItems[category] = {};
|
||||
}
|
||||
|
||||
const type = meta.type || 'topLevel';
|
||||
if (!menuItems[category][type]) {
|
||||
menuItems[category][type] = [];
|
||||
}
|
||||
|
||||
menuItems[category][type].push(meta);
|
||||
});
|
||||
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
export function ping(url, callback) {
|
||||
const img = new Image();
|
||||
let done;
|
||||
const finish = (status) => {
|
||||
if (!done) {
|
||||
done = true;
|
||||
img.src = '';
|
||||
callback(status);
|
||||
}
|
||||
};
|
||||
img.onload = () => finish('responded');
|
||||
img.onerror = () => finish('error');
|
||||
img.src = url;
|
||||
setTimeout(() => finish('timeout'), 1500);
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
const contentTmpl = './template/Content/index';
|
||||
|
||||
export default {
|
||||
categoryOrder: {
|
||||
组件: 0,
|
||||
@ -14,20 +12,13 @@ export default {
|
||||
Navigation: 3,
|
||||
Other: 4,
|
||||
},
|
||||
redirects: {
|
||||
CHANGELOG: 'docs/react/changelog',
|
||||
},
|
||||
docVersions: {
|
||||
'0.9.x': 'http://09x.ant.design/',
|
||||
'0.10.x': 'http://010x.ant.design/',
|
||||
'0.11.x': 'http://011x.ant.design/',
|
||||
'0.12.x': 'http://012x.ant.design/',
|
||||
},
|
||||
routes: {
|
||||
'/': './template/Home/index',
|
||||
'/docs/practice/:children': contentTmpl,
|
||||
'/docs/pattern/:children': contentTmpl,
|
||||
'/docs/react/:children': contentTmpl,
|
||||
'/CHANGELOG': contentTmpl,
|
||||
'/components/:children': contentTmpl,
|
||||
'/docs/spec/:children': contentTmpl,
|
||||
'/docs/resource/:children': contentTmpl,
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue
Block a user