• 呀!这款markdown编辑器我太中意啦!


    📖阅读本文,您将收获

    • 了解到优秀的markdown产品wolainotion
    • markdown编辑器选型,多一个选择项
    • 学会如何使用Mildown

    一、markdown编辑器的槽点

    作为研发人员,我不相信您编写文档没有使用过markdown;如果使用markdown编写文档,那肯定是离不开一款markdown编辑器。

    但是呢,市面上markdown编辑器又有蛮多槽点的:

    • 大部分开源编辑器,它是编辑区与预览区分离

      上图为掘金平台使用的编辑器,编辑区与预览区分离老碍眼了。古板,我觉得两者结合做到所见即所得会更好。

    • 收费

      做到所见即所得的markdown编辑器,当然有,例如市面上的Typorawolainotion

      这三款编辑器产品,用过的人都说好,强烈推荐

      它们有个共同的问题:商业化,商业化的产品目的就是搞钱,所以呢,它们有部分高级功能是需要付费的。

      但对大部分无特殊功能要求的人,它们已经够用了。

    • 不开源

      Typorawolainotion产品,它们的源代码是没有开放出来的,我们想在项目中集成它们是不可能的。

    二、新宠儿:Milkdown

    GitHub Star数: 6k+

    Milkdown是什么?

    官方自我介绍:

    Milkdown 是一个轻量但强大的 WYSIWYG(所见即所得)的 markdown 编辑器

    为什么选择Milkdown?

    官方理由:

    • 为开发者提供一个免费开源解决方案
    • 不同于 NotionTypora 等商用软件,Milkdown是开源且永久免费的
    • 值得信赖,有强大的社区支撑

    在线体验:milkdown.dev/zh-hans/onl…

    GitHub: github.com/Saul-Mirone…

    2.1 安装并运行

    Mildown以插件驱动,它由核心模块、官方插件组成。

    安装核心模块:

    1. npm i @milkdown/core @milkdown/transformer @milkdown/prose @milkdown/ctx
    2. 复制代码

    创建Editor实例:

    1. import { Editor } from "@milkdown/core"
    2. Editor.make().create()
    3. 复制代码

    执行,两行代码就报错啦!!

    • 错误1:Uncaught (in promise) Timing InitReady timeout.

      原因是缺少主题,再安装一个主题包:

    1. npm i @milkdown/theme-nord
    2. 复制代码
    1. import { Editor } from "@milkdown/core"
    2. import { nord } from "@milkdown/theme-nord"
    3. Editor.make().use(nord).create()
    4. 复制代码
    1. 再次运行,紧接着第二个报错出现。
    2. 复制代码
    • 错误2:Uncaught (in promise) RangeError: Schema is missing its top node type ('doc')

      错误大概意思是缺少doc节点,这是原因缺少markdown预设指令插件。

      官方提供了两款插件:@milkdown/preset-commonmark、@milkdown/preset-gfm,推荐@milkdown/preset-gfm

      同样的,下载使用:

    1. import { Editor } from "@milkdown/core"
    2. import { nord } from "@milkdown/theme-nord"
    3. import {gfm} from "@milkdown/preset-gfm"
    4. Editor.make().use(nord).use(gfm).create()
    5. 复制代码

    至此,Milkdown成功运行。接下来,只需要按需添加插件。

    2.2 顶部工具栏插件

    1. npm i @milkdown/plugin-menu
    2. 复制代码

    还是链式调用use ,注册插件。

    1. import { Editor } from "@milkdown/core"
    2. import { nord } from "@milkdown/theme-nord"
    3. import { gfm } from "@milkdown/preset-gfm"
    4. // 工具栏
    5. import { menu } from '@milkdown/plugin-menu';
    6. Editor
    7. .make()
    8. .use(nord)
    9. .use(gfm)
    10. .use(menu)
    11. .create()
    12. 复制代码

    但得到的是一堆英文单词:

    功能是存在的,但展示有问题,需要把一堆英文单词替换成字体图标。

    1. import { Editor ,ThemeIcon} from "@milkdown/core"
    2. import { nord } from "@milkdown/theme-nord"
    3. import { gfm } from "@milkdown/preset-gfm"
    4. // 工具栏
    5. import { menu } from '@milkdown/plugin-menu';
    6. import { getIcon } from "./icon"
    7. Editor
    8. .make()
    9. .use(nord.override((emotion, manager) => {
    10. manager.set(ThemeIcon, (icon) => {
    11. if (!icon) return;
    12. return getIcon(icon);
    13. });
    14. }))
    15. .use(gfm)
    16. .use(menu)
    17. .create()
    18. 复制代码

    针对@milkdown/theme-nord 设置,添加一个getIcon 方法。

    icon 文件内容过多此处不粘贴,请移动GitHub阅读:github.com/CatsAndMice…

    另外需要加载字体图标资源:

    1. <html>
    2. //...
    3. <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
    4. </html>
    5. 复制代码

    2.3 复制粘贴插件

    1. import { clipboard } from '@milkdown/plugin-clipboard';
    2. 复制代码
    1. //...
    2. import { clipboard } from '@milkdown/plugin-clipboard';
    3. Editor
    4. .make()
    5. .use(nord.override((emotion, manager) => {
    6. manager.set(ThemeIcon, (icon) => {
    7. if (!icon) return;
    8. return getIcon(icon);
    9. });
    10. }))
    11. .use(gfm)
    12. .use(menu)
    13. .use(clipboard)
    14. .create()
    15. 复制代码

    2.4 选择工具栏插件

    1. npm i @milkdown/plugin-tooltip
    2. 复制代码

    设置工具栏选中后置顶:

    1. //...
    2. import { tooltipPlugin, tooltip } from '@milkdown/plugin-tooltip';
    3. Editor
    4. .make()
    5. .use(nord.override((emotion, manager) => {
    6. manager.set(ThemeIcon, (icon) => {
    7. if (!icon) return;
    8. return getIcon(icon);
    9. });
    10. }))
    11. .use(gfm)
    12. .use(menu)
    13. //新增
    14. .use(tooltip.configure(tooltipPlugin, {
    15. top: true,
    16. }))
    17. .create()
    18. 复制代码

    2.5 支持/ 命令插件

    1. npm i @milkdown/plugin-slash
    2. 复制代码

    输入/,自定义添加面板功能配置:

    1. import { defaultValueCtx, Editor, rootCtx, ThemeIcon, themeManagerCtx } from "@milkdown/core";
    2. //...
    3. import {slash,createDropdownItem,defaultActions,slashPlugin} from '@milkdown/plugin-slash';
    4. Editor
    5. .make()
    6. // 新增
    7. .use(slash.configure(slashPlugin, {
    8. config: (ctx) => {
    9. return ({ content, isTopLevel }) => {
    10. if (!isTopLevel) return null;
    11. if (!content) {
    12. return { placeholder: "键入文字或'/'选择" };
    13. }
    14. const mapActions = (action) => {
    15. const { id = "" } = action;
    16. switch (id) {
    17. case "h1":
    18. action.dom = createDropdownItem(
    19. ctx.get(themeManagerCtx),
    20. "标题1",
    21. "h1"
    22. );
    23. return action;
    24. //...
    25. default:
    26. return action;
    27. }
    28. };
    29. if (content.startsWith("/")) {
    30. return content === "/"
    31. ? {
    32. placeholder: " ",
    33. actions: defaultActions(ctx).map(mapActions)
    34. }
    35. : {
    36. actions: defaultActions(ctx, content).map(mapActions)
    37. };
    38. }
    39. return null;
    40. };
    41. }
    42. }))
    43. 复制代码

    2.6 设置默认内容及添加事件插件

    设置默认内容是核心模块提供的功能,不必安装插件。

    1. import { defaultValueCtx, Editor, rootCtx, ThemeIcon, themeManagerCtx } from "@milkdown/core";
    2. //...
    3. Editor.make()
    4. .config((ctx) => {
    5. ctx.set(rootCtx, document.querySelector('#app'));
    6. ctx.set(defaultValueCtx, "## 点赞+评论+关注=学会");
    7. })
    8. //...
    9. 复制代码

    添加事件:

    1. npm i @milkdown/plugin-listener
    2. 复制代码

    @milkdown/plugin-listener分别对应七个生命周期函数:

    事件名事件描述
    beforeMount挂载前
    mounted挂载后
    updated状态更新
    markdownUpdatedmarkdown 更新
    blur失焦
    focus聚焦
    destroy销毁
    1. //...
    2. import { listenerCtx, listener } from "@milkdown/plugin-listener"
    3. Editor.make()
    4. .config((ctx) => {
    5. ctx.set(rootCtx, document.querySelector('#app'));
    6. ctx.set(defaultValueCtx, "## 点赞+评论+关注=学会");
    7. //新增
    8. ctx.get(listenerCtx).markdownUpdated((ctx, markdown, prevMarkdown) => {
    9. console.log(markdown);
    10. });
    11. })
    12. //...
    13. 复制代码

    借助上述事件,可以自定义获取内容等功能。

    Milkdown官方还有其他功能插件,例如:图片上传等,文章不逐一列举了。

    文章演示代码已开放GitHub: github.com/CatsAndMice…

    三、结束语

    原创不易!如果我的文章对你有帮助,点赞+评论+关注就是对我的最大支持^_^。

  • 相关阅读:
    【3D人脸】MediaPipe Face Mesh 调研
    ns-3 多天线设置与ns-3信道设置
    应用程序程序的自助密码重置
    vulnhub_DeRPnStiNK靶机渗透测试
    Spring篇---第三篇
    优雅打印的随机名言
    在 Jupyter Notebook 中查看所使用的 Python 版本和 Python 解释器路径
    从根源解决问题:构建体系化BOM管理机制与解决方案
    【STL】用哈希表(桶)封装出unordered_set和unordered_map
    JavaScript之document对象最常用相关知识总结
  • 原文地址:https://blog.csdn.net/BASK2312/article/details/127864673