site: update

This commit is contained in:
Benjy Cui 2016-05-24 10:17:32 +08:00
parent 6e59cae163
commit 0d0b6b0a32
23 changed files with 113 additions and 270 deletions

View File

@ -1,3 +1,5 @@
const path = require('path');
module.exports = {
source: ['./components', './docs'],
theme: './site/theme',
@ -7,10 +9,17 @@ module.exports = {
'./site/bisheng-plugin-antd',
],
webpackConfig(config) {
config.resolve.root = process.cwd();
config.resolve.alias = {
antd: process.cwd(),
site: 'site',
};
config.module.loaders.forEach((loader) => {
if (loader.test.toString() !== '/\\.md$/') return;
loader.loaders.splice(1, 0, path.join(process.cwd(), 'site/bisheng-markdown-react-loader'));
});
config.babel.plugins.push([
require.resolve('babel-plugin-antd'),
{

View File

@ -40,7 +40,7 @@ english: Icon
### 一. 方向性图标
```__react
import IconSet from '../../site/component/IconSet';
import IconSet from 'site/theme/template/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);

View File

@ -157,6 +157,7 @@ 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;

View File

@ -7,7 +7,7 @@ title: 可收起展开的侧边导航
````jsx
import { Menu, Breadcrumb, Icon } from 'antd';
import BrowserDemo from 'site/component/BrowserDemo';
import BrowserDemo from 'site/theme/template/BrowserDemo';
const SubMenu = Menu.SubMenu;
const AsideCollapse = React.createClass({

View File

@ -9,7 +9,7 @@ title: 侧边导航
````jsx
import { Menu, Breadcrumb, Icon } from 'antd';
import BrowserDemo from 'site/component/BrowserDemo';
import BrowserDemo from 'site/theme/template/BrowserDemo';
const SubMenu = Menu.SubMenu;
ReactDOM.render(

View File

@ -9,7 +9,7 @@ title: 吊顶规范
````jsx
import { Menu, Breadcrumb } from 'antd';
import BrowserDemo from 'site/component/BrowserDemo';
import BrowserDemo from 'site/theme/template/BrowserDemo';
ReactDOM.render(
<BrowserDemo>

View File

@ -7,7 +7,7 @@ title: 顶部导航 + 侧边栏
````jsx
import { Menu, Breadcrumb, Icon } from 'antd';
import BrowserDemo from 'site/component/BrowserDemo';
import BrowserDemo from 'site/theme/template/BrowserDemo';
const SubMenu = Menu.SubMenu;
ReactDOM.render(

View File

@ -11,7 +11,7 @@ title: 顶部导航
````jsx
import { Menu, Breadcrumb } from 'antd';
import BrowserDemo from 'site/component/BrowserDemo';
import BrowserDemo from 'site/theme/template/BrowserDemo';
ReactDOM.render(
<BrowserDemo>

View File

@ -89,6 +89,7 @@
"eslint-plugin-markdown": "*",
"eslint-plugin-react": "^5.0.1",
"eslint-tinker": "^0.3.1",
"esprima-fb": "^15001.1001.0-dev-harmony-fb",
"history": "^2.0.1",
"intl": "^1.2.2",
"intl-locales-supported": "^1.0.0",
@ -113,6 +114,7 @@
"react-router": "^2.0.0",
"react-stateless-wrapper": "^1.0.2",
"react-sublime-video": "^0.2.0-beta",
"recast": "^0.11.5",
"reqwest": "^2.0.5",
"values.js": "^1.0.3",
"webpack-babel-jest": "^1.0.4"

View File

@ -0,0 +1,58 @@
'use strict';
const recast = require('recast');
const builders = recast.types.builders;
// WAITING: esprima will support JSX
const parseOptions = {
parser: require('esprima-fb'),
};
function isImport(node) {
return node.type === 'ImportDeclaration';
}
function isNotImport(node) {
return !isImport(node);
}
module.exports = (content) => {
if (this.cacheable) {
this.cacheable();
}
let imports = [];
const ast = recast.visit(recast.parse(content, parseOptions), {
visitArrayExpression(path) {
const node = path.node;
const firstItem = node.elements[0];
const secondItem = node.elements[1];
if (firstItem &&
firstItem.type === 'Literal' &&
firstItem.value === 'pre' &&
secondItem.properties[0].value.value === '__react') { // TODO
const codeAst = recast.parse(node.elements[2].elements[1].value, parseOptions);
const astProgramBody = codeAst.program.body;
const codeImports = astProgramBody.filter(isImport);
imports = imports.concat(codeImports);
const codeBody = astProgramBody.filter(isNotImport);
const lastIndex = codeBody.length - 1;
codeBody[lastIndex] = builders.returnStatement(
codeBody[lastIndex].expression.arguments[0]
);
return builders.functionExpression(null, [
builders.identifier('React'), // TODO
builders.identifier('ReactDOM'),
], builders.blockStatement(codeBody));
}
this.traverse(path);
},
});
ast.program.body = imports.concat(ast.program.body);
return recast.print(ast).code;
};

View File

@ -1,5 +1,15 @@
const JsonML = require('jsonml.js/lib/utils');
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, '-');
@ -26,13 +36,19 @@ module.exports = (markdownData) => {
markdownData.content = contentChildren.slice(0, codeIndex);
}
markdownData.code = contentChildren[codeIndex];
markdownData.highlightedCode = contentChildren[codeIndex].slice(0, 2);
markdownData.preview = [
'pre', { lang: '__react' },
].concat(JsonML.getChildren(contentChildren[codeIndex]));
const styleNode = contentChildren.find((node) => {
return JsonML.getTagName(node) === 'pre' &&
JsonML.getAttributes(node).lang === 'css';
return isStyleTag(node) ||
(JsonML.getTagName(node) === 'pre' && JsonML.getAttributes(node).lang === 'css');
});
if (styleNode) {
if (isStyleTag(styleNode)) {
markdownData.style = JsonML.getChildren(styleNode)[0];
} else if (styleNode) {
markdownData.style = getCode(styleNode);
markdownData.highlightedStyle = JsonML.getAttributes(styleNode).highlighted;
}

View File

@ -6,10 +6,14 @@ module.exports = (markdownData) => {
return JsonML.getTagName(node) === 'h2' &&
JsonML.getChildren(node)[0] === 'API';
});
const content = contentChildren.slice(0, apiStartIndex);
const api = contentChildren.slice(apiStartIndex);
markdownData.content = ['section'].concat(content);
markdownData.api = ['section'].concat(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;
};

View File

@ -1,131 +0,0 @@
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')
);

View File

@ -1,120 +0,0 @@
/* 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');
}
};
}

View File

@ -12,3 +12,6 @@ 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';

View File

@ -110,7 +110,7 @@ export default class ComponentDoc extends React.Component {
props.utils.toReactComponent(
['section', {
className: 'markdown api-container',
}].concat(getChildren(doc.api || []))
}].concat(getChildren(doc.api || ['placeholder']))
)
}
</article>

View File

@ -1,4 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
const isLocal = location.port;
@ -32,9 +33,9 @@ export default class Demo extends React.Component {
const {
meta,
src,
preview,
content,
code,
preview,
highlightedCode,
style,
highlightedStyle,
} = props;
@ -61,7 +62,7 @@ export default class Demo extends React.Component {
{
meta.iframe ?
<iframe src={isLocal ? src : src.replace('./_site', '')} /> :
preview
preview(React, ReactDOM)
}
{
!!style ?
@ -83,7 +84,7 @@ export default class Demo extends React.Component {
<section className={highlightClass}
key="code">
<div className="highlight">
{props.utils.toReactComponent(code)}
{props.utils.toReactComponent(highlightedCode)}
</div>
{
highlightedStyle ?