從 simplemde 寫入 + inline-attachment 圖片拖拽上傳 到 parsedown 解析

Rachel發表於2019-03-23

準備工作

安裝富文字編輯器 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 協議》,轉載必須註明作者和本文連結

相關文章