RaoHai
9 years ago
72 changed files with 726 additions and 742 deletions
@ -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> |
@ -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; |
|||
}, |
|||
}; |
@ -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'; |
@ -0,0 +1,14 @@ |
|||
.clearfix { |
|||
zoom: 1; |
|||
&:before, |
|||
&:after { |
|||
content: " "; |
|||
display: table; |
|||
} |
|||
&:after { |
|||
clear: both; |
|||
visibility: hidden; |
|||
font-size: 0; |
|||
height: 0; |
|||
} |
|||
} |
@ -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> |
|||
); |
|||
} |
@ -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,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,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() { |
@ -1,5 +1,6 @@ |
|||
import React from 'react'; |
|||
import { Link } from 'react-router'; |
|||
import './index.less'; |
|||
|
|||
export default function NotFound() { |
|||
return ( |
@ -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,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') |
|||
); |
@ -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); |
|||
} |
Loading…
Reference in new issue