提交 e69968f5 编写于 作者: J Jason Park 提交者: Jason

Let description be written in markdown

上级 9831354d
const path = require('path');
const fs = require('fs');
const lebab = require('lebab');
const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1);
const latex = v => {
return v.replace(/\$([^$]+)\$/g, (m, m1) => `<img src="https://latex.codecogs.com/svg.latex?${m1.replace(/ /g, '')}"/>`)
};
const categories = fs.readdirSync(path.resolve(__dirname, '..', 'algorithm'));
for (const category of categories) {
......@@ -8,14 +12,11 @@ for (const category of categories) {
const algorithms = fs.readdirSync(path.resolve(__dirname, '..', 'algorithm', category));
for (const algorithm of algorithms) {
if (algorithm.startsWith('.')) continue;
const filepath = path.resolve(__dirname, '..', 'algorithm', category, algorithm, 'code.js');
const oldCode = fs.readFileSync(filepath, 'utf-8');
const dir = path.resolve(__dirname, '..', 'algorithm', category, algorithm);
try {
const { code: newCode, warnings } = lebab.transform(oldCode, ['let', 'arrow', 'multi-var', 'template', 'default-param', 'includes']);
// fs.writeFileSync(filepath, newCode, 'utf-8');
fs.renameSync(path.resolve(dir, 'desc.md'), path.resolve(dir, 'desc.json'));
// fs.unlinkSync(path.resolve(dir, 'desc.json'));
} catch (e) {
console.log(filepath);
console.error(e);
}
}
}
\ No newline at end of file
......@@ -29,10 +29,7 @@ const getWiki = (req, res, next) => {
if (!wiki) return next(new NotFoundError());
const wikiPath = getPath(wiki.name);
fs.readFile(wikiPath, 'utf8', (err, wiki) => {
if (err) return next(err);
res.json({ wiki });
});
res.sendFile(wikiPath);
};
router.route('/')
......
import React from 'react';
import { connect } from 'react-redux';
import { classes } from '/common/util';
import { actions as envActions } from '/reducers/env';
import styles from './stylesheet.scss';
import { DirectoryApi } from '/apis/index';
import { MarkdownViewer } from '/components';
@connect(
({ env }) => ({
......@@ -17,81 +16,37 @@ class DescriptionViewer extends React.Component {
super(props);
this.state = {
description: null,
source: null,
};
}
componentDidMount() {
const { categoryKey, algorithmKey } = this.props.env;
this.loadDescription(categoryKey, algorithmKey);
const href = `/algorithm/${categoryKey}/${algorithmKey}`;
this.loadMarkdown(href);
}
componentWillReceiveProps(nextProps) {
const { categoryKey, algorithmKey } = nextProps.env;
if (categoryKey !== this.props.env.categoryKey ||
algorithmKey !== this.props.env.algorithmKey) {
this.loadDescription(categoryKey, algorithmKey);
const href = `/algorithm/${categoryKey}/${algorithmKey}`;
this.loadMarkdown(href);
}
}
loadDescription(categoryKey, algorithmKey) {
DirectoryApi.getFile(categoryKey, algorithmKey, 'desc.json')
.then(description => this.setState({ description }));
}
getChild(value) {
if (typeof value === 'string') {
return (
<p>{value}</p>
);
} else if (Array.isArray(value)) {
return (
<ul className={styles.applications}>
{
value.map((li, i) => (
<li key={i} dangerouslySetInnerHTML={{ __html: li }} />
))
}
</ul>
);
} else if (typeof value === 'object') {
return (
<ul>
{
Object.keys(value).map((key, i) => (
<li className={styles.complexity} key={i}>
<span className={styles.complexity_type}>{key}: </span>
<span>{value[key]}</span>
</li>
))
}
</ul>
);
}
loadMarkdown(href) {
const [, , categoryKey, algorithmKey] = href.split('/');
DirectoryApi.getFile(categoryKey, algorithmKey, 'desc.md')
.then(source => this.setState({ source }));
}
render() {
const { description } = this.state;
const { className } = this.props;
return description && (
<div className={classes(styles.description_viewer, className)}>
{
Object.keys(description).map((key, i) => {
if (key === 'files') return null;
const value = description[key];
return (
<div key={i}>
<h3>{key}</h3>
{this.getChild(value)}
</div>
);
})
}
</div>
const { source } = this.state;
return (
<MarkdownViewer source={source} onClickLink={href => this.loadMarkdown(href)} />
);
}
}
export default DescriptionViewer;
......@@ -6,7 +6,6 @@ import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import faAngleRight from '@fortawesome/fontawesome-free-solid/faAngleRight';
import faCaretDown from '@fortawesome/fontawesome-free-solid/faCaretDown';
import faCaretRight from '@fortawesome/fontawesome-free-solid/faCaretRight';
import faPencilAlt from '@fortawesome/fontawesome-free-solid/faPencilAlt';
import faShare from '@fortawesome/fontawesome-free-solid/faShare';
import faPlay from '@fortawesome/fontawesome-free-solid/faPlay';
import faChevronLeft from '@fortawesome/fontawesome-free-solid/faChevronLeft';
......@@ -69,7 +68,6 @@ class Header extends React.Component {
icon={navigatorOpened ? faCaretDown : faCaretRight} />
</Button>
<div className={styles.top_menu_buttons}>
<Button icon={faPencilAlt} primary>Generate</Button>
<Button icon={faShare} primary>
Share
<input type="text" className={classes(styles.collapse, styles.shared)} />
......
import React from 'react';
import ReactMarkdown from 'react-markdown'
import { classes } from '/common/util';
import styles from './stylesheet.scss';
class MarkdownViewer extends React.Component {
render() {
const { className, source, onClickLink } = this.props;
const link = ({ href, ...rest }) => {
return /^https?:\/\//.test(href) ? (
<a href={href} rel="noopener" target="_blank" {...rest} />
) : (
<a onClick={() => onClickLink(href)} {...rest} />
);
};
const image = ({ src, ...rest }) => {
let newSrc;
const codecogs = 'https://latex.codecogs.com/svg.latex?';
if (src.startsWith(codecogs)) {
const latex = src.substring(codecogs.length);
newSrc = `${codecogs}\\color{White}${latex}`;
} else {
newSrc = src;
}
return <img src={newSrc} {...rest} />
};
return (
<ReactMarkdown className={classes(styles.markdown_viewer, className)} source={source}
renderers={{ link, image }} escapeHtml={false} />
);
}
}
export default MarkdownViewer;
@import "~/common/stylesheet/index";
.markdown_viewer {
display: flex;
flex-direction: column;
align-items: stretch;
padding: 16px;
font-size: $font-size-large;
overflow-y: auto;
a {
text-decoration: underline;
cursor: pointer;
}
}
\ No newline at end of file
import React from 'react';
import ReactMarkdown from 'react-markdown'
import { classes } from '/common/util';
import { WikiApi } from '/apis';
import styles from './stylesheet.scss';
import { MarkdownViewer } from '/components';
class WikiViewer extends React.Component {
constructor(props) {
super(props);
this.state = {
wiki: null,
source: null,
};
}
componentDidMount() {
this.loadWiki('Tracer');
this.loadMarkdown('Tracer');
}
loadWiki(wikiKey) {
WikiApi.getWiki(wikiKey)
.then(({ wiki }) => this.setState({ wiki: `# ${wikiKey}\n${wiki}` }));
loadMarkdown(href) {
WikiApi.getWiki(href)
.then(source => this.setState({ source }));
}
render() {
const { className } = this.props;
const { wiki } = this.state;
const InnerLink = ({ href, ...rest }) => {
return /^\w+$/.test(href) ? (
<a {...rest} onClick={() => this.loadWiki(href)} />
) : (
<a href={href} rel="noopener" target="_blank" {...rest} />
);
};
const { source } = this.state;
return (
<ReactMarkdown className={classes(styles.wiki_viewer, className)} source={wiki} renderers={{ link: InnerLink }}>
</ReactMarkdown>
<MarkdownViewer source={source} onClickLink={href => this.loadMarkdown(href)} />
);
}
}
......
......@@ -6,6 +6,7 @@ export { default as Ellipsis } from './Ellipsis';
export { default as ExpandableListItem } from './ExpandableListItem';
export { default as Header } from './Header';
export { default as ListItem } from './ListItem';
export { default as MarkdownViewer } from './MarkdownViewer';
export { default as Navigator } from './Navigator';
export { default as ToastContainer } from './ToastContainer';
export { default as WikiViewer } from './WikiViewer';
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册