MarkDown在线编辑器

项目简介

要求实现一个在线markdown编辑器,支持markdown文件的在线编辑,修改,重新加载,转化为html格式等。

Pandao MarkDown编辑器

Pandao MarkDown是基于BootStrap和jquery实现的MarkDown编辑器,已经支持MarkDown在线编辑功能,我们要做的是做一个demo把Pando MarkDown的功能调用起来,形成一整套的发布,编辑,修改等流程。
Pandao MarkDown 的官网https://pandao.github.io/editor.md/
Pandao MarkDown 的项目地址https://github.com/pandao/editor.md

发布页面

实现发布页面publish.html,这个页面不做过多粘贴,只截取一小部分作示例,详细的文件在这里https://cdn.llfc.club/publish.html

  1. <link rel="stylesheet" href="editormd/css/editormd.css" />
  2. <div id="test-editor">
  3. <textarea style="display:none;">### 关于 Editor.md
  4. **Editor.md** 是一款开源的、可嵌入的 Markdown 在线编辑器(组件),基于 CodeMirror、jQuery 和 Marked 构建。
  5. </textarea>
  6. </div>
  7. <script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
  8. <script src="editormd/editormd.min.js"></script>
  9. <script type="text/javascript">
  10. $(function() {
  11. var editor = editormd("test-editor", {
  12. // width : "100%",
  13. // height : "100%",
  14. path : "editormd/lib/"
  15. });
  16. });
  17. </script>

为id为test-editor的div生成了markdown编辑器,我们可以看一下效果
https://cdn.llfc.club/1668079260340.jpg

markdown转化为html

将markdown转化为html,需要使用markdownToHTML函数,这个函数需要传入一个节点用来接收转化生成的html。
在publish.html中再添加一个按钮用来发布文章,和一个id为”test-markdown-view”的div用来接收生成的html

  1. <div class="container-fluid" id="article-publish">
  2. <div class="row">
  3. <div class="col publish-btn-parent">
  4. <button type="button" class="btn btn-primary" id="publish-post-btn">发布文章</button>
  5. <button type="button" class="btn btn-primary" id="return-index-btn">返回列表</button>
  6. </div>
  7. </div>
  8. <div class="row">
  9. <div class="col">
  10. <div id="test-markdown-view" class="">
  11. <!-- Server-side output Markdown text -->
  12. <textarea style="display:none;">### Hello world!</textarea>
  13. </div>
  14. </div>
  15. </div>
  16. </div>

接下来实现markdown转化为html的逻辑

  1. //获取md内容转化为html
  2. var testView = editormd.markdownToHTML("test-markdown-view", {
  3. markdown: $("textarea.editormd-markdown-textarea").text(),
  4. });
  5. //组装json发送给服务器
  6. let post_data = {
  7. "md-content": $("textarea.editormd-markdown-textarea").text(),
  8. "html-content": $("#test-markdown-view").prop("outerHTML"),
  9. "title": title,
  10. }
  11. $.ajax({
  12. type: "post",
  13. contentType: "application/json;charset=utf-8",
  14. data: JSON.stringify(post_data),
  15. url: "/publish-article",
  16. dataType: "json",
  17. async: false,
  18. success: function (data) {
  19. if (data.errorcode != 0) {
  20. alert(`request error , code is ${data.errorcode}`)
  21. return;
  22. }
  23. window.location.href = '/'
  24. },
  25. error: function (XMLHttpRequest, textStatus, errorThrown) {
  26. // 状态码
  27. console.log(XMLHttpRequest.status);
  28. // 状态
  29. console.log(XMLHttpRequest.readyState);
  30. // 错误信息
  31. console.log(textStatus);
  32. }
  33. });

将md转化为html放在了id为”test-markdown-view”的div下,然后组装post_data,将markdown和html内容都发送给了服务器,服务器存储起来,方便下次修改时读取。

显示文章

因为服务器已经存储了html和markdown内容,接下来显示文章只需要读取html就可以了
先实现一个获取文章内容的函数

  1. //请求单个文章的详情
  2. function GetArticleDetail(article_id) {
  3. let post_data = { 'article_id': article_id }
  4. $.ajax(
  5. {
  6. type: "post",
  7. contentType: "application/json;charset=utf-8",
  8. data: JSON.stringify(post_data),
  9. url: "/article-detail",
  10. dataType: "json",
  11. async: false,
  12. success: function (data) {
  13. if (data.errorcode != 0) {
  14. alert(`request error , code is ${data.errorcode}`)
  15. return;
  16. }
  17. console.log("get article deatail is ", data)
  18. //编译模板的里的内容
  19. var template = Handlebars.compile($('#template-article-info').html());
  20. //把后台获取到的数据student渲染到页面
  21. $('#article-info-div').html(template(data['article-detail']));
  22. $('#article-title-div>h1').html(data['article-detail'].title);
  23. $('.article-div').html(data['article-detail']['html-content'])
  24. },
  25. error: function (XMLHttpRequest, textStatus, errorThrown) {
  26. // 状态码
  27. console.log(XMLHttpRequest.status);
  28. // 状态
  29. console.log(XMLHttpRequest.readyState);
  30. // 错误信息
  31. console.log(textStatus);
  32. }
  33. }
  34. )
  35. }

在函数GetArticleDetail里我们将服务器传过来的数据通过模板编译显示在html里,并且获取了”html-content”放在$(‘.article-div’)节点下。
服务器的逻辑就不赘述了,可以见文章底部的源码链接。
文章页面article.html简要列举一段

  1. <div class="row">
  2. <div class="col" id="article-info-div">
  3. <script type="text/x-handlebars-template" id="template-article-info">
  4. <div class="row ">
  5. <div class="col article-div" id={{artid}} data-created={{created}} data-title={{title}}>
  6. </div>
  7. </div>
  8. </script>
  9. </div>
  10. </div>
  11. <script src="/static/js/jquery.min.js"></script>
  12. <script src="/static/js/handlebars.js"></script>
  13. <script src="/static/js/index.js"></script>
  14. <script>
  15. $(function () {
  16. var pathnames = window.location.pathname.split('/')
  17. if (pathnames.length < 3) {
  18. console.log("invalid url")
  19. return;
  20. }
  21. var article_id = pathnames[2]
  22. GetArticleDetail(article_id)
  23. });
  24. </script>

所以实现过后文章页面的效果大体是这个样子
https://cdn.llfc.club/1668081722889.jpg

再次编辑

对于已经发布的文章,有时候需要再次编辑,这个时候可以通过前端向服务器发送请求获取存储的markdown,编辑markdown之后生成新的html,再次发送给服务器,以达到更新文章的目的.
简单列举一下edit.html的内容

  1. <div class="container-fluid">
  2. <div class="row">
  3. <div id="test-editor" class="col">
  4. <textarea style="display:none;">### Editor.md
  5. **Editor.md**: The open source embeddable online markdown editor, based on CodeMirror & jQuery & Marked.
  6. </textarea>
  7. </div>
  8. </div>
  9. </div>
  10. <div class="container-fluid" id="article-publish">
  11. <div class="row">
  12. <div class="col publish-btn-parent">
  13. <button type="button" class="btn btn-primary" id="publish-edit-btn">更新文章</button>
  14. <button type="button" class="btn btn-primary" id="return-index-btn">返回列表</button>
  15. </div>
  16. </div>
  17. <div class="row">
  18. <div class="col">
  19. <div id="test-markdown-view" class="">
  20. <!-- Server-side output Markdown text -->
  21. <textarea style="display:none;">### Hello world!</textarea>
  22. </div>
  23. </div>
  24. </div>
  25. </div>

和public.html类似,edit.html也包含更新按钮以及id为“test-editor”的div,该div用来存储markdown内容。
id为”test-markdown-view”的div用来存储markdown转化的html内容。
我们在页面里生成editor编辑器,并且从服务器获取markdown内容写入id为”test-editor”的div里

  1. <script>
  2. $(function () {
  3. var editor = editormd("test-editor", {
  4. height: '800px',
  5. syncScrolling: "single",
  6. emoji: true,
  7. //启动本地图片上传功能
  8. imageUpload: true,
  9. watch: true,
  10. imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp", "zip", "rar"],
  11. path: "./editormd/lib/",
  12. imageUploadURL: "./upload.php", //文件提交请求路径
  13. saveHTMLToTextarea: true, //注意3:这个配置,方便post提交表单
  14. previewTheme: "dark",//预览主题样式 默认白色 dark为黑色
  15. });
  16. })
  17. </script>
  18. <script>
  19. $(function () {
  20. var pathnames = window.location.pathname.split('/')
  21. if (pathnames.length < 3) {
  22. console.log("invalid url")
  23. return;
  24. }
  25. var article_id = pathnames[2]
  26. GetArticleEdit(article_id)
  27. // console.log('window.location.pathname is ', window.location.pathname.split('/'))
  28. });
  29. </script>

GetArticleEdit 这个函数用来从服务器获取markdown数据拼接到div上

  1. //请求单个文章编辑页面内容
  2. function GetArticleEdit(article_id) {
  3. let post_data = { 'article_id': article_id }
  4. $.ajax(
  5. {
  6. type: "post",
  7. contentType: "application/json;charset=utf-8",
  8. data: JSON.stringify(post_data),
  9. url: "/article-detail",
  10. dataType: "json",
  11. async: false,
  12. success: function (data) {
  13. if (data.errorcode != 0) {
  14. alert(`request error , code is ${data.errorcode}`)
  15. return;
  16. }
  17. console.log("get article deatail is ", data)
  18. $("textarea.editormd-markdown-textarea").text(data['article-detail']['md-content'])
  19. $("#title-input").val(data['article-detail']['title'])
  20. $("#title-input").attr('data-artid', data['article-detail']['artid'])
  21. },
  22. error: function (XMLHttpRequest, textStatus, errorThrown) {
  23. // 状态码
  24. console.log(XMLHttpRequest.status);
  25. // 状态
  26. console.log(XMLHttpRequest.readyState);
  27. // 错误信息
  28. console.log(textStatus);
  29. }
  30. }
  31. )
  32. }

所以通过这些逻辑我们实现了编辑功能,进入编辑页面后自动将服务器存储的markdown内容加载到页面上,编辑页面基本是这个样子
https://cdn.llfc.club/1668129289749.jpg
这样就实现了在线编辑,重新发布的功能。

总结

整体来看,通过我们的重组和架构可以实现markdown文档的在线编辑和发布。
感兴趣的可以看看我的源码,源码地址如下
https://gitee.com/secondtonone1/pandaomd-pro
原文链接
https://llfc.club/articlepage?id=2HNduA4HWE8iMt06GH4uUi2cWLy

热门评论

热门文章

  1. 解密定时器的实现细节

    喜欢(566) 浏览(1143)
  2. C++ 类的继承封装和多态

    喜欢(588) 浏览(1271)
  3. Linux环境搭建和编码

    喜欢(594) 浏览(2009)
  4. windows环境搭建和vscode配置

    喜欢(587) 浏览(1290)
  5. slice介绍和使用

    喜欢(521) 浏览(1297)

最新评论

  1. interface应用 secondtonone1:interface是万能类型,但是使用时要转换为实际类型来使用。interface丰富了go的多态特性,也降低了传统面向对象语言的耦合性。
  2. 面试题汇总(一) secondtonone1:看到网络上经常提问的go的问题,做了一下汇总,结合自己的经验给出的答案,如有纰漏,望指正批评。
  3. slice介绍和使用 恋恋风辰:切片作为引用类型极大的提高了数据传递的效率和性能,但也要注意切片的浅拷贝隐患,算是一把双刃剑,这世间的常态就是在两极之间寻求一种稳定。
  4. Linux环境搭建和编码 恋恋风辰:Linux环境下go的安装比较简单,可以不用设置GOPATH环境变量,后期我们学习go mod 之后就拜托了go文件目录的限制了。
  5. 构造函数 secondtonone1:构造函数是类的基础知识,要着重掌握

个人公众号

个人微博