前言
大家好啊,这里是懂一点项目管理和前端开发的狗子。
最近狗子的人生已经重启完毕,即将开始React开发的新篇章。但说实话,我React开发的技术确实还在基础水平,想检验一下自己的项目开发能力。
于是藜麦计划就诞生了,这是藜麦计划的第一个项目,纯练手项目,不喜勿喷。
计划说
因为是第一篇嘛,俺没计划写一篇文章作为大纲简介 (后续可能写),所以暂时先写在这,所有文章以项目形式发布,所以大佬们看到项目的某一篇文章,就可以找到所有该项目的文章。
Markdown编辑器
第一个项目我预计分为三篇文章讲述我如何开发一个纯前端 的Markdown编辑器功能(模仿的是xx,你懂的),太过高级的功能后续持续随缘开发 ,主要是基础功能的讲解,欢迎大佬们吐槽。
Markdown编辑器(一 · 需求及思路)
这一篇文章主要是讲需求,如果大致了解了Markdown需求的大佬们,可以直接移步下一篇文章。
- 我们要做什么?什么是Markdown?
- 如何做?
- 整体思路及流程
- 总结
Markdown编辑器(二 · 核心代码开发)
这一篇主要讲述基础功能的开发 和部分逻辑的优化
- 基础显示
- 列表 - 有序,无序
- 任务列表
....
- 总结
Markdown编辑器(三 · 高级功能及优化)
这一篇主要讲述的是一些稍微复杂的功能实践 ,同时修改上一篇的逻辑问题。
- 代码块
- 表格
- 总结
正文
我们要做什么?什么是Markdown?
万物皆可项目,凡是项目先要明白项目需求是什么,有了需求之后才能知道开发的方向。
项目制定
目标:我们需要完成一个markdown的编辑器(纯前端)
基本语法 :Markdown 语法速查表
借鉴网站 :掘金文章编辑器(自己写一篇就知道了),markdown 编辑器
好处:
- 了解了Markdown内部实现逻辑
- 加深了正则表达式的了解
- 熟悉了React项目的开发
- 学会了github.io的部署
如何做?
那如何做呢?
俗话说:要致富,先修路。
咱们先把核心的逻辑理清楚,其他的拼拼凑凑也能用。
敲黑板! 核心的来了哈!
基础方案:用正则表达式匹配Markdown语法的各种写法
正则表达式匹配
首先呢,打开你们的文心一言 、豆包 、Bing AI 、ChatGPT等AI工具。
标题匹配
输入Prompt:写一个正则,用于解析markdown语法中的标题
ok,我们就能得到一个正则表达式:
js
const regex = /^\s*#{1,6}\s+/
大家获得到的正则可能不一致,可以先用起来,看能不能正常匹配到标题。
意思是:
- 匹配
#
字符,它可能会出现1-6个。 #
字符前会出现0-1个空白符,后面会出现1+个空白符。
这样,标题的核心就拿到了,接下来拿加粗的核心
文本加粗
按照标题的方案以此类推
输入Prompt:写一个正则,用于解析markdown语法中的加粗文字
js
const regex = /\*\*(.*?)\*\*|__(.*?)__/g
意思是:
**
和__
分别匹配两个星号或两个下划线,他们都可以表示加粗。(.*?)
是一个非贪婪匹配,用于捕获两个星号或下划线之间的任意字符(即要加粗的文字)。|
是或运算符,表示匹配前面的模式或后面的模式。
根据我提供的标题 和文本加粗,大家举一反三,将其他的正则都可以获取到(有bug就解决bug),后续写其他格式的时候,我也会将正则写出来,用于给大家参考。
整体思路及流程
在核心逻辑解决的情况下,接下来可以梳理整体项目的设计了,于是我们可以开始概要设计了。
我们最终的效果大概是酱紫的:
模块划分及流程图
基础流程比较简单:输入 - 分析 - 渲染
根据AI提供的方向,我们一共需要做这几个模块:
PS:具体什么是AST我就不多说了,基础文章太多。
PSS:只是我们的AST是自定义的,并非已有的AST语法树。
为什么?
很明显,如果不是很明白思路的大佬们会问:为什么要词法分析和语法分析?
我是写了2天才慢慢明白为什么的
词法分析 主要是分析每一行或者是每一个模块里面有什么 ,然后统一放到一起,相当于创建了一个一维数组,每一行就是一个数据。它没办法去匹配文字中所有相同的模块,因为会导致乱序(当然,你有更好的办法就说)。
语法分析 主要是组合在词法分析中有关联的模块(语法),并且生成一个AST ,AST中能够更加精确地描述出当前语句和上下文有什么关系。
以上就是我的理解
大概想法已经确定,接下来开始编码。
基础项目搭建(可跳过)
我的项目是基于 Antd 的React + TS项目,所以搭建比较简单,这里不做要求,大家各自搭建自己的项目即可。
PS:这里吐槽一句,确实TS在写这种Demo的时候很耗时间,当然了,也很好查问题。
然后在src中创建一个markdown文件夹
然后再加入当前非常好用的Tailwind CSS!省掉我们写大量css代码的解决方案。
Install Tailwind CSS with Vite
基础文件创建(扫一眼就行)
index
创建index.tsx
用于渲染我们的markdown页面,整体的结构也非常简单(样例看上面的图):
左←输入框,右→显示框
输入框我们直接使用Antd的TextArea
,右侧排版使用的是Typography
排版组件。
再加上一些边边角角的样式,于是主函数就生成了:
PS:我最上层div定义了一个固定的宽高,所以class可以用
h-full
。
tsx
export default function MarkdownToHtml() {
const [markdownText, setMarkdownText] = useState(textDemo);
// TODO 分词,解析为tokens
// TODO 根据上一步所得到的tokens,形成AST
const ast = {};
return (
<>
<div className="h-full w-full flex backdrop-opacity-10 backdrop-invert rounded">
<div style={{ flex: `0 0 40rem` }}>
<MarkdownInput defaultValue={markdownText} onChange={setMarkdownText} />
</div>
<Typography className="w-full p-2 text-left border
border-stone-300 border-solid rounded">
{/* <GenerateHtml node={ast} /> */}
</Typography>
</div>
</>
);
}
输入框暂时没有特别复杂,一起写到index文件中,后期如果写复杂了,就抽离出来。
tsx
function MarkdownInput({ onChange, defaultValue }: {
onChange: (value: string) => void;
defaultValue?: string
}) {
return (
<>
<div className="h-full">
<TextArea
defaultValue={defaultValue}
placeholder="Write markdown"
style={{ height: '100%', resize: 'none', backgroundColor: 'rgba(255, 255, 255, 0.8)' }}
onChange={e => {
onChange(e.target.value);
}} />
</div>
</>
)
}
最终结果渲染
大家在上面看到了我有一个GenerateHtml
组件注释了,也没有写到index里面,主要还是觉得这一块会很大,里面的if逻辑会挺多,所以单独拿出来了。
创建一个generate-html
文件
不过这块是下一篇文章的内容,暂时就写一个空的标签
tsx
export default function GenerateHtml({ node }: Props) {
return <></>;
}
GenerateHtml
组件主要是根据AST结构渲染成不同的节点,例如对于文字的一些效果,我们就可以在Antd文档里面找到:
常量和类型
按照规范,我们所有常量文件全部放入到 const.ts
中,例如上面已经获取到的正则表达式。
类型文件也丢到type.d.ts
中
词法分析和语法分析
这一块也是第二章主要讲解的内容,暂时先创建两个文件:tokenize.ts
和parse.ts
。
tokenize用于解析输入原文,转换为token。
parse用于整合token,转为AST。
总结
以上就是项目初期做的准备,良好的项目需要一个简单的开始。
这一篇文章我们了解到了几个问题:
为什么要做
该怎么做
前期如何准备
下一章的链接已经在上面给大家了,有想法的大佬们请继续品尝。