Browse Source

Revert "refactor with bisheng"

pull/1869/head
RaoHai 9 years ago
parent
commit
7a07b128d1
  1. 2
      .gitignore
  2. 9
      404.html
  3. 2
      components/icon/index.md
  4. 4
      components/input-number/demo/digit.md
  5. 2
      components/locale-provider/demo/all.md
  6. 1
      docs/spec/colors.md
  7. 2
      docs/spec/layout/demo/aside-collapse.md
  8. 2
      docs/spec/layout/demo/aside.md
  9. 2
      docs/spec/layout/demo/ceiling.md
  10. 2
      docs/spec/layout/demo/top-aside.md
  11. 2
      docs/spec/layout/demo/top.md
  12. 1
      docs/spec/motion.md
  13. 5
      index.html
  14. 7
      package.json
  15. 50
      site/bisheng-plugin-antd/lib/browser.js
  16. 11
      site/bisheng-plugin-antd/lib/node.js
  17. 90
      site/bisheng-plugin-antd/lib/process-demo.js
  18. 19
      site/bisheng-plugin-antd/lib/process-doc.js
  19. 34
      site/bisheng-plugin-antd/lib/template.html
  20. 34
      site/bisheng.config.js
  21. 18
      site/common/lib.js
  22. 14
      site/common/styles/clearfix.less
  23. 0
      site/common/styles/colors.less
  24. 2
      site/common/styles/common.less
  25. 10
      site/common/styles/demo.less
  26. 0
      site/common/styles/font.less
  27. 0
      site/common/styles/footer.less
  28. 0
      site/common/styles/highlight.less
  29. 1
      site/common/styles/markdown.less
  30. 0
      site/common/styles/mock-browser.less
  31. 0
      site/common/styles/motion.less
  32. 0
      site/common/styles/new-version-info-modal.less
  33. 0
      site/common/styles/page-nav.less
  34. 0
      site/common/styles/preview-img.less
  35. 0
      site/common/styles/resource.less
  36. 0
      site/common/styles/responsive.less
  37. 0
      site/common/styles/toc.less
  38. 13
      site/component/App.jsx
  39. 90
      site/component/Article/index.jsx
  40. 0
      site/component/BrowserDemo/index.jsx
  41. 131
      site/component/ComponentDoc/index.jsx
  42. 50
      site/component/Demo/index.jsx
  43. 4
      site/component/Footer/index.jsx
  44. 33
      site/component/Header/index.jsx
  45. 22
      site/component/Header/index.less
  46. 0
      site/component/Home/Banner.jsx
  47. 0
      site/component/Home/Link.jsx
  48. 0
      site/component/Home/Page1.jsx
  49. 0
      site/component/Home/Page2.jsx
  50. 2
      site/component/Home/Page3.jsx
  51. 0
      site/component/Home/Page4.jsx
  52. 33
      site/component/Home/index.jsx
  53. 0
      site/component/Home/index.less
  54. 0
      site/component/IconSet/CopyableIcon.jsx
  55. 0
      site/component/IconSet/index.jsx
  56. 0
      site/component/ImagePreview/index.jsx
  57. 75
      site/component/MainContent/index.jsx
  58. 1
      site/component/NotFound/index.jsx
  59. 0
      site/component/NotFound/index.less
  60. 0
      site/component/VideoPlayer/index.jsx
  61. 80
      site/component/utils.js
  62. 0
      site/entry/en-US.js
  63. 131
      site/entry/index.jsx
  64. 120
      site/entry/utils.js
  65. 0
      site/entry/zh-CN.js
  66. 18
      site/theme/static/style.js
  67. 77
      site/theme/template/Content/Article.jsx
  68. 120
      site/theme/template/Content/ComponentDoc.jsx
  69. 11
      site/theme/template/Content/index.jsx
  70. 70
      site/theme/template/Layout/index.jsx
  71. 46
      site/theme/template/utils.jsx
  72. 15
      site/website.config.js

2
.gitignore

@ -23,6 +23,6 @@ nohup.out
_site
_data
dist
/lib
lib
elasticsearch-*
config/base.yaml

9
404.html

@ -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>

2
components/icon/index.md

@ -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);

4
components/input-number/demo/digit.md

@ -1,6 +1,6 @@
---
order: 3
title: 小数
- order: 3
- title: 小数
---
和原生的数字输入框一样,value 的精度由 step 的小数位数决定。

2
components/locale-provider/demo/all.md

@ -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>

1
docs/spec/colors.md

@ -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;

2
docs/spec/layout/demo/aside-collapse.md

@ -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({

2
docs/spec/layout/demo/aside.md

@ -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(

2
docs/spec/layout/demo/ceiling.md

@ -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>

2
docs/spec/layout/demo/top-aside.md

@ -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(

2
docs/spec/layout/demo/top.md

@ -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>

1
docs/spec/motion.md

@ -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;

5
site/theme/static/template.html → index.html

@ -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>

7
package.json

@ -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",

50
site/bisheng-plugin-antd/lib/browser.js

@ -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} />;
}],
],
};
};

11
site/bisheng-plugin-antd/lib/node.js

@ -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);
};

90
site/bisheng-plugin-antd/lib/process-demo.js

@ -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;
};

19
site/bisheng-plugin-antd/lib/process-doc.js

@ -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;
};

34
site/bisheng-plugin-antd/lib/template.html

@ -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>

34
site/bisheng.config.js

@ -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

@ -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

@ -0,0 +1,14 @@
.clearfix {
zoom: 1;
&:before,
&:after {
content: " ";
display: table;
}
&:after {
clear: both;
visibility: hidden;
font-size: 0;
height: 0;
}
}

0
site/theme/static/colors.less → site/common/styles/colors.less

2
site/theme/static/common.less → site/common/styles/common.less

@ -34,7 +34,7 @@ a {
position: relative;
}
div.main-container {
.main-container {
padding: 0 6% 120px 4%;
margin-left: -1px;
background: #fff;

10
site/theme/static/demo.less → site/common/styles/demo.less

@ -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;
}

0
site/theme/static/font.less → site/common/styles/font.less

0
site/theme/static/footer.less → site/common/styles/footer.less

0
site/theme/static/highlight.less → site/common/styles/highlight.less

1
site/theme/static/markdown.less → site/common/styles/markdown.less

@ -99,6 +99,7 @@
.markdown pre code {
border: none;
padding: 1em 2em;
background: #f7f7f7;
margin: 0;
font-size: 13px;

0
site/theme/static/mock-browser.less → site/common/styles/mock-browser.less

0
site/theme/static/motion.less → site/common/styles/motion.less

0
site/theme/static/new-version-info-modal.less → site/common/styles/new-version-info-modal.less

0
site/theme/static/page-nav.less → site/common/styles/page-nav.less

0
site/theme/static/preview-img.less → site/common/styles/preview-img.less

0
site/theme/static/resource.less → site/common/styles/resource.less

0
site/theme/static/responsive.less → site/common/styles/responsive.less

0
site/theme/static/toc.less → site/common/styles/toc.less

13
site/component/App.jsx

@ -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

@ -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>
);
}
}

0
site/theme/template/BrowserDemo.jsx → site/component/BrowserDemo/index.jsx

131
site/component/ComponentDoc/index.jsx

@ -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>
);
}
}

50
site/theme/template/Content/Demo.jsx → site/component/Demo/index.jsx

@ -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 ?

4
site/theme/template/Layout/Footer.jsx → site/component/Footer/index.jsx

@ -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() {

33
site/theme/template/Layout/Header.jsx → site/component/Header/index.jsx

@ -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>

22
site/theme/static/header.less → site/component/Header/index.less

@ -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;
}
}

0
site/theme/template/Home/Banner.jsx → site/component/Home/Banner.jsx

0
site/theme/template/Home/Link.jsx → site/component/Home/Link.jsx

0
site/theme/template/Home/Page1.jsx → site/component/Home/Page1.jsx

0
site/theme/template/Home/Page2.jsx → site/component/Home/Page2.jsx

2
site/theme/template/Home/Page3.jsx → site/component/Home/Page3.jsx

@ -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" />

0
site/theme/template/Home/Page4.jsx → site/component/Home/Page4.jsx

33
site/theme/template/Home/index.jsx → site/component/Home/index.jsx

@ -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>
);
}
}

0
site/theme/static/home.less → site/component/Home/index.less

0
site/theme/template/IconSet/CopyableIcon.jsx → site/component/IconSet/CopyableIcon.jsx

0
site/theme/template/IconSet/index.jsx → site/component/IconSet/index.jsx

0
site/bisheng-plugin-antd/lib/ImagePreview.jsx → site/component/ImagePreview/index.jsx

75
site/theme/template/Content/MainContent.jsx → site/component/MainContent/index.jsx

@ -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
site/theme/template/NotFound.jsx → site/component/NotFound/index.jsx

@ -1,5 +1,6 @@
import React from 'react';
import { Link } from 'react-router';
import './index.less';
export default function NotFound() {
return (

0
site/theme/static/not-found.less → site/component/NotFound/index.less

0
site/bisheng-plugin-antd/lib/VideoPlayer.jsx → site/component/VideoPlayer/index.jsx

80
site/component/utils.js

@ -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);
}

0
site/theme/en-US.js → site/entry/en-US.js

131
site/entry/index.jsx

@ -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

@ -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');
}
};
}

0
site/theme/zh-CN.js → site/entry/zh-CN.js

18
site/theme/static/style.js

@ -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';

77
site/theme/template/Content/Article.jsx

@ -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>
);
}
}

120
site/theme/template/Content/ComponentDoc.jsx

@ -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>
);
}
}

11
site/theme/template/Content/index.jsx

@ -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>
);
};

70
site/theme/template/Layout/index.jsx

@ -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>
);
};

46
site/theme/template/utils.jsx

@ -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);
}

15
site/theme/index.js → site/website.config.js

@ -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…
Cancel
Save