从 simplemde 写入 + inline-attachment 图片拖拽上传 到 parsedown 解析

准备工作

安装富文本编辑器 sparksuite/simplemde-markdown-editor (感谢 Bestony 推荐)

yarn add simplemde --save

安装 markedjs/marked , 在 JS 中解析 markdown, 用于在编辑页面预览

yarn add marked

安装 erusev/parsedown , 在 php 中解析 markdown (感谢 Summer 鉴定并推荐) 

composer require erusev/parsedown

----- 下面是代码部分了, 一共涉及两个页面-----

编辑页面

HTML 部分:
{{--文本输入框--}}
<textarea name="content" id="editor"></textarea>
JS 部分:
// 用于生成预览的 js 文件
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
// 用于富文本编辑器的 js 文件
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
// 富文本编辑器的配置
<script>
var simplemde = new SimpleMDE({
            element: $("#editor")[0],
            autofocus: true,
            autosave: {
                enabled: true,
                uniqueId: "#editor",
                delay: 1000,
            },
            blockStyles: {
                bold: "__",
                italic: "_"
            },
            forceSync: true,
            hideIcons: ["guide", "heading"],
            indentWithTabs: false,
            insertTexts: {
                horizontalRule: ["", "\n\n-----\n\n"],
                image: ["![](http://", ")"],
                link: ["[", "](http://)"],
                table: ["", "\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text     | Text      | Text     |\n\n"],
            },
            parsingConfig: {
                allowAtxHeaderWithoutSpace: true,
                strikethrough: false,
                underscoresBreakWords: true,
            },
            placeholder: "下笔如有神",
            // 在编辑页面生成预览
            previewRender: function(plainText, preview) { // Returns HTML from a custom parser, Async method
                setTimeout(function(){
                    preview.innerHTML = marked(plainText);
                }, 250);
                return "预览生成中......";
            },
            // 用 highlight.js 使代码高亮, 仅预览时生效
            renderingConfig: {
                codeSyntaxHighlighting: true,
            },
        });
</script>

展示页面

HTML 部分:
{{--用于代码高亮的样式文件--}}
<link href="https://cdn.bootcss.com/highlight.js/9.15.6/styles/a11y-dark.min.css" rel="stylesheet">
{{--内容输出--}}
{!! Parsedown::instance()->text($post->content) !!}
JS 部分:
// 用于代码高亮的 JS 文件
<script src="https://cdn.bootcss.com/highlight.js/9.15.6/highlight.min.js"></script>
// for 代码高亮
hljs.initHighlightingOnLoad();

以上, 就是从入到出的全过程, 这个编辑器的视觉效果还蛮好的, 简洁优雅.

But, 桑心的是它不支持图片上传功能, 也不支持表情. 希望走过路过的大神能随手丢几个 tips, 不胜感激.


2019年4月6日更新 --- 增加图片拖拽功能

一直很想解决这个问题,但是没有方向, 终于有天看到了 [@Destiny](https://learnku.com/users/4430)搭建博客必备:图片拖动文本框自动上传。讲的非常的细致。今天满怀开心加兴奋地想要实践到自己的项目里. 如果只是普通的文本域, 真的很好用. 但是, 由于我原本用的是 simplemde 编辑器,按照 Destiny 的方法拖拽不生效。看到评论区 [@hedeqiang](https://learnku.com/users/20847) 同学也遇到同样的问题,并用 codemirror 解决了,非常感激提供思路。 但是貌似实现的过程并不简单,因为如果只是简单的换个 js 文件的引用,就会多出一个文本框....... Whatever, 直接记录下我最终实现的过程吧.

首先是在官网下载包, 然后把下面提到的 js 文件存到自己的项目里.

// 引入下面的文件
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/codemirror/4.0.3/codemirror.js"></script>
<script src="../js/inline-attachment.js"></script>
<script src="../js/codemirror-4.inline-attachment.js"></script>

// 这里是生成的 simplemde 对象
var simplemde = new SimpleMDE(.........);

// 在已有的 simplemde 对象的基础上再增加图片拖拽
inlineAttachment.editors.codemirror4.attach(simplemde.codemirror, {
    // 传递 CSRF token
    extraParams: {
        '_token': "{{ csrf_token() }}",
            },

    // 设置图片上传的地址
    uploadUrl: '{{ route('web.posts.imagesUpload') }}',

    // 上传之后的处理
    onFileUploadResponse: function(xhr) {
        var result = JSON.parse(xhr.responseText),
        filename = result[this.settings.jsonFieldName];

        if (result && filename) {
            var newValue;
            if (typeof this.settings.urlText === 'function') {
                        newValue = this.settings.urlText.call(this, filename, result);
                    } else {
                        newValue = this.settings.urlText.replace(this.filenameTag, filename);
                    }
                    var text = this.editor.getValue().replace(this.lastValue, newValue);
                    this.editor.setValue(text);
                    this.settings.onFileUploaded.call(this, filename);
                }
                return false;
            }
        });

php 接收图片并上传到阿里云

public function imagesUpload(Request $request)
    {
        $file = $request->file();

        // 我这里是对图片做了个裁切
        $filename = $this->upload($file['file'], 500);

        return \Response::json([
            // 这个返回的 'filename' 是根据 inline-attachment.js 文件里的默认配置写的
            'filename' => $filename
        ]);
    }

因为 upload 方法比较常用, 所以我单独提出来放在父级 controller 里:

protected function upload($file, $size)
    {
        $image = Image::make($file->getRealPath())->fit($size)->encode('jpg');
        $filename = 'files/' . date('Y-m-d-h-i-s') . '-' . $file->getClientOriginalName();
        $bool = Storage::disk('oss')->put($filename, $image->__toString());
        if ($bool) {
            return $filename;
        } else {
            return '';
        }
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer 于 5年前 加精
讨论数量: 3

我用这个 markdown 编辑器的时候,在编辑器代码里加 asset(){{ csrf_token() }} 会出现

file
导致页面不能打开,这个有什么办法解决吗?

4年前 评论

@仙人球上一点红 或者是 route() 之类的都会包没有这个方法

4年前 评论

上传图片不支持webp :flushed:

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!