site: refactor

This commit is contained in:
Benjy Cui 2016-04-01 16:52:47 +08:00
parent 2cda36a7c4
commit ed591cd7e4
5 changed files with 70 additions and 98 deletions

View File

@ -72,7 +72,7 @@
"warning": "~2.1.0"
},
"devDependencies": {
"antd-md-loader": "0.1.0-beta.18",
"antd-md-loader": "~0.1.0",
"atool-build": "^0.6.5",
"babel-cli": "^6.2.0",
"babel-core": "^6.2.1",
@ -97,9 +97,9 @@
"eslint-plugin-react": "^4.0.0",
"eslint-tinker": "^0.3.1",
"gh-pages": "^0.11.0",
"highlight.js": "^9.2.0",
"history": "^1.17.0",
"jest-cli": "~0.8.0",
"jsonml-to-react-component": "~0.1.0",
"jsonp": "^0.2.0",
"lesshint": "^1.2.1",
"lodash": "^4.1.0",

View File

@ -25,12 +25,15 @@ export default class Article extends React.Component {
}
imgToPreview(node) {
if (!this.isPreviewImg(node.children)) {
return node;
if (node[0] === 'p' &&
node[1][0] === 'innerHTML' &&
this.isPreviewImg(node[1][1])) {
const imgs = node.slice(1)
.map((n) => n[1])
.filter((img) => img);
return <ImagePreview imgs={imgs} />;
}
const imgs = node.children.split(/\r|\n/);
return <ImagePreview imgs={imgs} />;
return node;
}
isVideo(string) {
@ -38,49 +41,57 @@ export default class Article extends React.Component {
}
enhanceVideo(node) {
if (!this.isVideo(node.children)) {
return node;
if (node[0] === 'innerHTML' && this.isVideo(node[1])) {
return <VideoPlayer video={node[1]} />;
}
return <VideoPlayer video={node.children} />;
return node;
}
render() {
const { content, location } = this.props;
const jumper = content.description.filter((node) => {
return node.type === 'h2';
return node[0] === 'h2';
}).map((node) => {
return (
<li key={node.children}>
<Link to={{ pathname: location.pathname, query: { scrollTo: node.children } }}
dangerouslySetInnerHTML={{ __html: node.children }} />
<li key={node[1]}>
<Link to={{ pathname: location.pathname, query: { scrollTo: node[1] } }}
dangerouslySetInnerHTML={{ __html: node[1] }} />
</li>
);
});
content.description = content.description
.map(this.imgToPreview)
.map(this.enhanceVideo);
const { meta, intro } = content;
const description = content.description
.map(this.imgToPreview)
.map(this.enhanceVideo);
return (
<article className="markdown">
<h1>
{ content.meta.chinese || content.meta.english }
{ meta.chinese || meta.english }
{
!content.meta.subtitle ? null :
<span className="subtitle">{ content.meta.subtitle }</span>
!meta.subtitle ? null :
<span className="subtitle">{ meta.subtitle }</span>
}
</h1>
{
!content.intro ? null :
content.intro.map(utils.objectToComponent.bind(null, location.pathname))
!intro ? null :
utils.jsonmlToComponent(
location.pathname,
['section', { className: 'markdown' }].concat(intro)
)
}
{
jumper.length > 0 ?
<section className="toc"><ul>{ jumper }</ul></section> :
null
}
{ content.description.map(utils.objectToComponent.bind(null, location.pathname)) }
{
utils.jsonmlToComponent(
location.pathname,
['section', { className: 'markdown' }].concat(description)
)
}
</article>
);
}

View File

@ -82,7 +82,13 @@ export default class ComponentDoc extends React.Component {
</Affix>
<section className="markdown">
<h1>{meta.chinese || meta.english}</h1>
{ description.map(utils.objectToComponent.bind(null, location.pathname)) }
{
utils.jsonmlToComponent(
location.pathname,
['section', { className: 'markdown' }]
.concat(description)
)
}
<h2>
代码演示
<Icon type="appstore" className={expandTriggerClass}
@ -103,9 +109,14 @@ export default class ComponentDoc extends React.Component {
<Col className="code-boxes-col-2-1" span="12">{ rightChildren }</Col>
}
</Row>
<section className="markdown api-container">
{ (doc.api || []).map(utils.objectToComponent.bind(null, location.pathname)) }
</section>
{
utils.jsonmlToComponent(
location.pathname,
['section', {
className: 'markdown api-container',
}].concat(doc.api || [])
)
}
</article>
);
}

View File

@ -33,8 +33,7 @@ export default class Demo extends React.Component {
[className]: className,
expand: codeExpand,
});
const introChildren = intro.map(utils.objectToComponent.bind(null, pathname));
const introChildren = utils.jsonmlToComponent(pathname, ['div'].concat(intro));
return (
<section className={codeBoxClass} id={id}>
<section className="code-box-demo">

View File

@ -1,79 +1,30 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Link } from 'react-router';
import hljs from 'highlight.js';
import toReactComponent from 'jsonml-to-react-component';
function isHeading(type) {
return /h[1-6]/i.test(type);
}
function mdLangToHljsLang(lang) {
return lang.toLowerCase() === 'jsx' ?
'javascript' :
lang;
}
export function objectToComponent(pathname, object, index) {
if (object === null) return;
if (React.isValidElement(object)) {
return React.cloneElement(object, { key: index });
}
if (typeof object === 'function') {
return React.cloneElement(object(React, ReactDOM), { key: index });
}
if (typeof object === 'string') {
return <span key={index}>{ object }</span>;
}
const children = object.children;
if (object.type === 'html') {
return React.createElement('div', {
className: 'markdown',
key: index,
dangerouslySetInnerHTML: { __html: children }
});
}
if (isHeading(object.type)) {
return React.createElement(object.type, {
key: index,
id: children,
}, [
<span key="title" dangerouslySetInnerHTML={{ __html: object.children }} />,
<Link to={{ pathname, query: { scrollTo: object.children } }} className="anchor" key="anchor">#</Link>,
]);
}
if (object.type === 'code') {
const highlightedCode = hljs.highlight(
mdLangToHljsLang(object.props.lang),
children
).value;
return (
<div className="highlight" key={index}>
<pre>
<code className={object.props.lang}
dangerouslySetInnerHTML={{ __html: highlightedCode }} />
</pre>
</div>
);
}
if (typeof children === 'string') {
return React.createElement(object.type, {
key: index,
dangerouslySetInnerHTML: { __html: children }
});
}
return React.createElement(
object.type, { key: index },
children && children.map(objectToComponent.bind(null, pathname)) // `hr` has no children
);
export function jsonmlToComponent(pathname, jsonml) {
return toReactComponent([
[(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(node[0]), (node, index) => {
return React.createElement(node[0], {
key: index,
id: node[1],
}, [
<span key="title" dangerouslySetInnerHTML={{ __html: node[1] }} />,
<Link to={{ pathname, query: { scrollTo: node[1] } }} className="anchor" key="anchor">#</Link>,
]);
}],
], jsonml);
}
export function setTitle(title) {