安装
将代码保存至tinymce/plugins/catchremoteimage/plugin.(min.)js不存在新建
然后在编辑器配置的plugins项新增catchremoteimage加载插件
然后在编辑器新增cri插件配置

配置
下面上传回调uploader中使用了jquery的ajax,如果你的项目使用其他框架请替换为自己框架的ajax功能


// 粘贴内容远程图片本地化
cri: {
    white_domains: ['cfyun.cc', 'cfyun.top'],
    uploader: function(images, success, error) {
        if(!images) {
            return !1;
        }
        let data = new FormData();
        // 需要本地化的图片地址
        data.append('urls', images);


        // 额外参数, formData为自定义的参数,例如: { uid: 1, token: 'token string' }
        $.each(formData, function(aKey, aVal) {
            if(typeof aVal == 'object') { // 如果是object则用jquery的val方法取得内容
                aVal = aVal.val();
            }
            data.append(aKey, aVal);
        });


        $.ajax({
            url: options.uploadUrl,
            method: 'post',
            data: data,
            cache: !1,
            contentType: !1,
            processData: !1,
            forceSync: !1,
            beforeSend: function(jqXHR, settings) {
                jqXHR.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
                jqXHR.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            }
        }).then((res) => {
            if(res.errno == 0) {
                // 在表单内插入已上传附件记录, 用于提交数据保存关系
                if(editorImageListElem.length && res.data.list && res.data.list.length) {
                    $.each(res.data.list, function(k, v) {
                        editorImageListElem.append('<input type="hidden" name="images[]" value="' + v.aid + '">');
                    });
                }
                success(res.data);
                return !1;
            }
            error(res.message || res.data);
        }).catch((_error) => {
            error(_error || '远程图片本地化失败,请重试!');
        });
    }
}, 


还有2个编辑器自带的配置项必须设置

{
    paste_data_images: true,
    images_file_types: 'jpeg,jpg,png,gif,bmp,webp,svg',
}

插件代码



(function () {
    'use strict';

    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    var $ = tinymce.util.Tools.resolve('tinymce.dom.DomQuery');

    class CatchRemoteImage {
        constructor(editor) {

            var options = editor.getParam('cri', {}, 'object');

            if(!options || !options.uploader) {
                return !1;
            }

            if(!options.white_domains) {
                options.white_domains = null;
            }

            this.images = [];
            this.editor = editor;
            this.options = options;

            let _this = this;

            this.event();

            return this;
        };
        /**
         * 监听编辑器粘贴
         */
        event() {
            let _this = this;
            // 粘贴远程图片本地化
            this.editor.on('paste', function(e) {
                let images = [];
                const items = _this.editor.getDoc().getElementsByTagName('img');
                if(items.length) {
                    for (var i = 0, img; img = items[i++];) {
                        if (img.getAttribute('word_img')) {
                            continue;
                        }
                        var src = img.getAttribute('data-src') || img.getAttribute('_src') || img.src || '';
                        if (/^(https?|ftp):/img.test(src) && !_this.checkDomain(src)) {
                            images.push(src);
                        }
                    }
                }
                if (images.length) {
                    _this.uploadImage(images, (data) => {
                        var i, o, item, res, _src, __src, list = data.list;
                        for (i = 0; item = items[i++];) {
                            _src = item.getAttribute('data-src') || item.getAttribute('_src') || item.src || '';
                            for (o = 0; res = list[o++];) {
                                if (_src == res.source && res.state == 'success') {// 抓取失败时不做替换处理
                                    __src = res.url;
                                    _this.replaceImage(item, res);
                                    break;
                                }
                            }
                        }
                        _this.editor.save();
                    },
                    (error) => {
                        _this.editor.notificationManager.open({
                            text: error || '上传出错,请重试~',
                            type: 'error',
                            timeout: 3000,
                        });
                    });
                }
            });
        };
        // 白名单检测
        checkDomain(url) {
            if (url.indexOf(location.host) !== -1 || /(^\.)|(^\/)/.test(url)) {
                return !0;
            }
            if (!this.options.white_domains) {
                return !0;
            }

            for (let domain in this.options.white_domains) {
                if (this.options.white_domains.hasOwnProperty(domain) && url.indexOf(this.options.white_domains[domain]) !== -1) {
                    return !0;
                }
            }

            return !1;
        };
        // 替换原有外部图片为本地化后的图片地址
        replaceImage(image, data) {
            let _this = this;
            const each = function (xs, f) {
                for (var i = 0, len = xs.length; i < len; i++) {
                    var x = xs[i];
                    f(x, i);
                }
            };
            const map = function (xs, f) {
                var len = xs.length;
                var r = new Array(len);
                for (var i = 0; i < len; i++) {
                    var x = xs[i];
                    r[i] = f(x, i);
                }
                return r;
            };
            const replaceString = function (content, search, replace) {
                let index = 0;
                do {
                    index = content.indexOf(search, index);
                    if (index !== -1) {
                        content = content.substring(0, index) + replace + content.substr(index + search.length);
                        index += replace.length - search.length + 1;
                    }
                } while (index !== -1);
                return content;
            };
            const replaceImageUrl = function (content, targetUrl, replacementUrl) {
                let replacementString = 'src="' + replacementUrl + '"';
                content = replaceString(content, 'src="' + targetUrl + '"', replacementString);
                content = replaceString(content, 'data-mce-src="' + targetUrl + '"', 'data-mce-src="' + replacementUrl + '"');
                return content;
            };
            const replaceUrlInUndoStack = function (targetUrl, replacementUrl) {
                each(_this.editor.undoManager.data, function (level) {
                    if (level.type === 'fragmented') {
                        level.fragments = map(level.fragments, function (fragment) {
                            return replaceImageUrl(fragment, targetUrl, replacementUrl);
                        });
                    } else {
                        level.content = replaceImageUrl(level.content, targetUrl, replacementUrl);
                    }
                });
            };
            let src = this.editor.convertURL(data.url, 'src');

            let attr = {
                'src': data.url,
                'data-mce-src': data.url,
                // 'data-app': data.app, // 自定义的img额外属性
                // 'data-aid': data.aid // 自定义的img额外属性
            };

            replaceUrlInUndoStack(image.src, data.url);
            $(image).attr(attr).removeAttr('alt');
        };
        // 将上传
        uploadImage(images, success, error) {
            // let data = new FormData();
            // data.append('urls', images);
            if(!this.options.uploader || typeof this.options.uploader !== 'function') {
                error('远程图片本地化:上传回调“cri.uploader”配置有误');
                return !1;
            }
            // 回调上传
            this.options.uploader(images, success, error);
        };
    };

    function Plugin () {
  global.add('catchremoteimage', function (editor) {
            editor.on('init', function (e) {
                new CatchRemoteImage(editor)
            });
        });
 }

 Plugin();

}()); 

(本文内容根据网络资料整理和来自用户投稿,出于传递更多信息之目的,不代表本站其观点和立场。也不对其真实性、可靠性承担任何法律责任,特此声明!)

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部