前段时间,一直在做数据分析方面的学习,所以采集不少公开的数据。
所以,打算做一个简单的网站来分享这些采集的数据,也方便其他学习数据分析的同学获取数据。
1. 选型原因
以前做项目用antd
和antd pro
比较多,所以本来打算用antd pro
来做一个管理数据的网站。
但是,采集来的数据文件差别很大,数据格式也差别很大,要想展示好数据,估计会在前端上浪费大量的时间。
而本来的目的只是分享数据而已,所以,也想过直接用markdown
来做个静态的网站,
每种数据用一个markdown
文件介绍即可,markdown
格式灵活,编写简单,足以胜任。
但是,markdown
的静态网站工具(比如 hugo 之类的),也有很多配置要学习,
而且以后如果有动态的功能要添加功能也不太方便。
于是,最后决定尝试用 antd pro
来搭建网站的整体结构,用markdown
文件作为每个不同的页面。
前端是 antd pro
的工程,
后端是golang
工程,后端很简单,通过API
将markdown
文件内容返回到前端。
之所以这样做,一是因为对 antd pro
比较熟悉,方便以后增加菜单,甚至增加其他功能页面;
二是后端虽然简单,目前只有一个API,但是扩展也方便,比如加认证,权限功能,甚至提供一些分析结果展示的服务也不无可能。
2. markdown渲染
目前的关键就在于markdown
的渲染,还好react
有现成的markdown
的渲染库。
本来以为只要几行代码就可以完成这个网站,然而实际做起来,果然处处有坑。。。
前端需要安装的主要库:
yarn add react-markdown
yarn add remark-gfm
2.1. 默认的渲染
因为是分享为主,对样式没什么特别要求,所以刚开始就直接用默认渲染的方式:
import { PageContainer } from '@ant-design/pro-components';
import { Card } from 'antd';
import React, { useEffect, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
const Home: React.FC = () => {
const [md, handleMD] = useState('loading... ...');
useEffect(() => {
fetch('/api/v1/file/markdown/home/home.md')
.then((resp) => resp.text())
.then((txt) => handleMD(txt));
}, [md]);
return (
<PageContainer>
<Card
style={{
borderRadius: 8,
}}
>
<ReactMarkdown
remarkPlugins={[[remarkGfm, { singleTilde: false }]]}
>
{md}
</ReactMarkdown>
</Card>
</PageContainer>
);
};
export default Home;
运行之后网页中的效果如下:
虽说事先预计到默认样式会很朴素,实在没想到会朴素到这个程度。。。
不仅表格和代码部分不突出,连标题也和普通文本一样。
也许是受到antd pro
整体的样式的影响,不管怎样,不优化是不行的了。
2.2. 表格的支持
首先要处理的表格的支持,因为打算做的是数据分享的网站,里面有很多介绍数据的表格。
为了覆盖antd
样式带来的影响,在github
上找了一个专门的markdown css
。
sindresorhus / github-markdown-css
它有几种css风格可以选择,这里我选择了默认的 github-markdown.css
,下载之后放到自己的工程中再引用即可。
import { PageContainer } from '@ant-design/pro-components';
import { Card } from 'antd';
import React, { useEffect, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import './github-markdown.css';
const Home: React.FC = () => {
// 省略。。。
return (
<PageContainer>
<Card
style={{
borderRadius: 8,
}}
>
<ReactMarkdown
className={'markdown-body'}
remarkPlugins={[[remarkGfm, { singleTilde: false }]]}
>
{md}
</ReactMarkdown>
</Card>
</PageContainer>
);
};
export default Home;
主要变化就在 上面的第6
行和第25
行。
加入css之后,效果如下:
立刻好看了很多,表格可以正常显示了,但是代码没有高亮。
2.3. 代码的支持
接下来解决代码的高亮显示,需要安装:
yarn add remark-code-blocks
yarn add react-syntax-highlighter
然后改造上面代码中的 ReactMarkdown
部分:
import { PageContainer } from '@ant-design/pro-components';
import { Card } from 'antd';
import React, { useEffect, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import remarkGfm from 'remark-gfm';
import './github-markdown.css';
const Home: React.FC = () => {
// 省略。。。
return (
<PageContainer>
<Card
style={{
borderRadius: 8,
}}
>
<ReactMarkdown
className={'markdown-body'}
remarkPlugins={[[remarkGfm, { singleTilde: false }]]}
components={{
// eslint-disable-next-line @typescript-eslint/no-unused-vars
code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<SyntaxHighlighter
{...props}
// eslint-disable-next-line react/no-children-prop
children={String(children).replace(/\n$/, '')}
style={oneDark}
language={match[1]}
PreTag="div"
/>
) : (
<code {...props} className={className}>
{children}
</code>
);
},
}}
>
{md}
</ReactMarkdown>
</Card>
</PageContainer>
);
};
export default Home;
显示效果如下:
最后的代码部分可以高亮显示了。
2.4. 图片的支持
最后,还有图片显示的支持。
图片的显示markdown
本来是支持的,只是图片默认都是原样大小来显示,造成图大字小,显示很不协调。
默认是这样的:
所以,根据图片的情况,设置其最大宽度:
const Wzry: React.FC = () => {
// 省略。。。
return (
<PageContainer header={{ breadcrumb: {} }}>
<Card
style={{
borderRadius: 8,
}}
>
<ReactMarkdown
className={'markdown-body'}
remarkPlugins={[[remarkGfm, { singleTilde: false }]]}
components={{
// 省略。。。
img(props) {
return <img {...props} style={{ maxWidth: 30 }} />;
},
}}
>
{md}
</ReactMarkdown>
</Card>
</PageContainer>
);
};
export default Wzry;
让图片的大小和文字能协调起来:
3. 后端主要代码
后端比较简单,主要就是用golang
的gin
框架实现了一个返回markdown
文件的API
。
// 路由部分
r.GET("/file/markdown/:filetype/:filename", controller.DownloadFileByName)
// API功能部分
func DownloadFileByName(c *gin.Context) {
filetype := c.Param("filetype")
filename := c.Param("filename")
cnf := config.Get()
p := path.Join(cnf.File.MarkdownDir, filetype, filename)
c.File(p)
}
4. 最后
目前这个简单的网站已经发布在 databook.top/
数据都是公开的真实数据,已整理成csv
文件(UTF8编码的,windows上直接用excel打开可能会乱码),后续会逐步添加其他类型的数据。
如果用excel打开的话,用导入文件的方式打开,导入文件时别忘了选择UTF8
编码。