前段时间,一直在做数据分析方面的学习,所以采集不少公开的数据。
所以,打算做一个简单的网站来分享这些采集的数据,也方便其他学习数据分析的同学获取数据。
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编码。