Procházet zdrojové kódy

富文本粘贴处理

dusenyao před 1 rokem
rodič
revize
1a3e157b48

+ 3 - 3
package-lock.json

@@ -4052,9 +4052,9 @@
       }
     },
     "core-js": {
-      "version": "3.35.0",
-      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.35.0.tgz",
-      "integrity": "sha512-ntakECeqg81KqMueeGJ79Q5ZgQNR+6eaE8sxGCx62zMbAIj65q+uYvatToew3m6eAGdU4gNZwpZ34NMe4GYswg=="
+      "version": "3.35.1",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.35.1.tgz",
+      "integrity": "sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw=="
     },
     "core-js-compat": {
       "version": "3.33.0",

+ 1 - 1
package.json

@@ -11,7 +11,7 @@
   "dependencies": {
     "@tinymce/tinymce-vue": "^3.2.8",
     "axios": "^1.6.5",
-    "core-js": "^3.35.0",
+    "core-js": "^3.35.1",
     "dompurify": "^3.0.8",
     "element-ui": "^2.15.14",
     "hanzi-writer": "^3.6.1",

+ 178 - 0
patches/tinymce+5.10.9.patch

@@ -0,0 +1,178 @@
+diff --git a/node_modules/tinymce/plugins/ax_wordlimit/index.js b/node_modules/tinymce/plugins/ax_wordlimit/index.js
+new file mode 100644
+index 0000000..02edc4d
+--- /dev/null
++++ b/node_modules/tinymce/plugins/ax_wordlimit/index.js
+@@ -0,0 +1,7 @@
++// Exports the "ax_wordlimit" plugin for usage with module loaders
++// Usage:
++//   CommonJS:
++//     require('tinymce/plugins/ax_wordlimit')
++//   ES2015:
++//     import 'tinymce/plugins/ax_wordlimit'
++require('./plugin.js');
+diff --git a/node_modules/tinymce/plugins/ax_wordlimit/plugin.js b/node_modules/tinymce/plugins/ax_wordlimit/plugin.js
+new file mode 100644
+index 0000000..bd4704d
+--- /dev/null
++++ b/node_modules/tinymce/plugins/ax_wordlimit/plugin.js
+@@ -0,0 +1,55 @@
++tinymce.PluginManager.add('ax_wordlimit', function(editor) {
++    var pluginName='字数限制';
++    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
++    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');
++    var ax_wordlimit_type = editor.getParam('ax_wordlimit_type', 'letter' );
++    var ax_wordlimit_num = editor.getParam('ax_wordlimit_num', false );
++    var ax_wordlimit_delay = editor.getParam('ax_wordlimit_delay', 500 );
++    var ax_wordlimit_callback = editor.getParam('ax_wordlimit_callback', function(){} );
++    var ax_wordlimit_event = editor.getParam('ax_wordlimit_event', 'SetContent Undo Redo Keyup' );
++    var onsign=1;
++    //统计方法1:计算总字符数
++    var sumLetter = function(){
++        var html = editor.getContent();
++        var re1 = new RegExp("<.+?>","g");
++        var txt = html.replace(re1,'');
++        txt = txt.replace(/\n/g,'');
++        txt = txt.replace(/&nbsp;/g,' ');
++        var num=txt.length;
++        return {txt:txt,num:num}
++    }
++    var onAct = function(){
++        if(onsign){
++            onsign=0;
++            //此处预留更多统计方法
++            switch(ax_wordlimit_type){
++                case 'letter':
++                default:
++                    var res = sumLetter();
++            }
++            if( res.num > ax_wordlimit_num ){
++                ax_wordlimit_callback(editor, res.txt, ax_wordlimit_num);
++            }
++            setTimeout(function(){onsign=1}, ax_wordlimit_delay);
++        }
++
++    }
++    var setup = function(){
++        if( ax_wordlimit_num>0 ){
++            global$2.setEditorTimeout(editor, function(){
++                var doth = editor.on(ax_wordlimit_event, onAct);
++            }, 300);
++        }
++    };
++
++    setup();
++
++    return {
++        getMetadata: function () {
++            return  {
++                name: pluginName,
++                url: "http://tinymce.ax-z.cn/more-plugins/ax_wordlimit.php",
++            };
++        }
++    };
++});
+diff --git a/node_modules/tinymce/plugins/ax_wordlimit/plugin.min.js b/node_modules/tinymce/plugins/ax_wordlimit/plugin.min.js
+new file mode 100644
+index 0000000..143777e
+--- /dev/null
++++ b/node_modules/tinymce/plugins/ax_wordlimit/plugin.min.js
+@@ -0,0 +1,55 @@
++tinymce.PluginManager.add('ax_wordlimit', function(editor) {
++    var pluginName='字数限制';
++    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
++    var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');
++    var ax_wordlimit_type = editor.getParam('ax_wordlimit_type', 'letter' );
++    var ax_wordlimit_num = editor.getParam('ax_wordlimit_num', false );
++    var ax_wordlimit_delay = editor.getParam('ax_wordlimit_delay', 500 );
++    var ax_wordlimit_callback = editor.getParam('ax_wordlimit_callback', function(){} );
++    var ax_wordlimit_event = editor.getParam('ax_wordlimit_event', 'SetContent Undo Redo Keyup' );
++    var onsign=1;
++    //统计方法1:计算总字符数
++    var sumLetter = function(){
++        var html = editor.getContent();
++        var re1 = new RegExp("<.+?>","g");
++        var txt = html.replace(re1,'');
++        txt = txt.replace(/\n/g,'');
++        txt = txt.replace(/&nbsp;/g,' ');
++        var num=txt.length;
++        return {txt:txt,num:num}
++    }
++    var onAct = function(){
++        if(onsign){
++            onsign=0;
++            //此处预留更多统计方法
++            switch(ax_wordlimit_type){
++                case 'letter':
++                default:
++                    var res = sumLetter();
++            }
++            if( res.num > ax_wordlimit_num ){
++                ax_wordlimit_callback(editor, res.txt, ax_wordlimit_num);
++            }
++            setTimeout(function(){onsign=1}, ax_wordlimit_delay);
++        }
++        
++    }
++    var setup = function(){
++        if( ax_wordlimit_num>0 ){
++            global$2.setEditorTimeout(editor, function(){
++                var doth = editor.on(ax_wordlimit_event, onAct);
++            }, 300);
++        }
++    };
++
++    setup();
++
++    return {
++        getMetadata: function () {
++            return  {
++                name: pluginName,
++                url: "http://tinymce.ax-z.cn/more-plugins/ax_wordlimit.php",
++            };
++        }
++    };
++});
+diff --git a/node_modules/tinymce/plugins/image/plugin.js b/node_modules/tinymce/plugins/image/plugin.js
+index 1691b27..5255b8c 100644
+--- a/node_modules/tinymce/plugins/image/plugin.js
++++ b/node_modules/tinymce/plugins/image/plugin.js
+@@ -8,7 +8,6 @@
+  */
+ (function () {
+     'use strict';
+-
+     var global$6 = tinymce.util.Tools.resolve('tinymce.PluginManager');
+ 
+     var __assign = function () {
+@@ -1407,7 +1406,7 @@
+               meta: {}
+             }
+           });
+-          api.showTab('general');
++          // api.showTab('general'); 切换 tab 为普通
+           changeSrc(helpers, info, state, api);
+         };
+         blobToDataUri(file).then(function (dataUrl) {
+@@ -1416,6 +1415,8 @@
+             helpers.uploadImage(blobInfo).then(function (result) {
+               updateSrcAndSwitchTab(result.url);
+               finalize();
++              helpers.onSubmit(info)(api); // 上传成功后,触发保存事件
++              updateSrcAndSwitchTab(""); // 保存事件成功后,清空 src
+             }).catch(function (err) {
+               finalize();
+               helpers.alertErr(err);
+diff --git a/node_modules/tinymce/tinymce.js b/node_modules/tinymce/tinymce.js
+index 3955a24..2988ecd 100644
+--- a/node_modules/tinymce/tinymce.js
++++ b/node_modules/tinymce/tinymce.js
+@@ -810,7 +810,7 @@
+     var lTrim = blank(/^\s+/g);
+     var rTrim = blank(/\s+$/g);
+     var isNotEmpty = function (s) {
+-      return s.length > 0;
++      return s?.length > 0;
+     };
+     var isEmpty$3 = function (s) {
+       return !isNotEmpty(s);

+ 13 - 2
src/components/common/RichText.vue

@@ -40,7 +40,7 @@ import 'tinymce/plugins/lists';
 import 'tinymce/plugins/media'; // 插入视频插件
 // import 'tinymce/plugins/template'; // 模板插件
 // import 'tinymce/plugins/fullscreen'; // 全屏插件
-// import 'tinymce/plugins/paste';
+import 'tinymce/plugins/paste'; // 粘贴插件
 // import 'tinymce/plugins/preview'; // 预览插件
 import 'tinymce/plugins/hr';
 import 'tinymce/plugins/autoresize'; // 自动调整大小插件
@@ -119,7 +119,7 @@ export default {
         min_height: this.height,
         width: '100%',
         autoresize_bottom_margin: 0,
-        plugins: 'link lists image hr media autoresize ax_wordlimit',
+        plugins: 'link lists image hr media autoresize ax_wordlimit paste',
         toolbar: this.toolbar, // 工具栏
         contextmenu: false, // 右键菜单
         menubar: false, // 菜单栏
@@ -149,6 +149,17 @@ export default {
         file_picker_types: 'media', // 文件上传类型
         file_picker_callback: this.filePickerCallback,
         init_instance_callback: this.isFill ? this.initInstanceCallback : '',
+        paste_enable_default_filters: false, // 禁用默认的粘贴过滤器
+        // 粘贴预处理
+        paste_preprocess(plugin, args) {
+          let content = args.content;
+          // 使用正则表达式去掉 style 中的 background 属性
+          content = content.replace(/background(-color)?:[^;]+;/g, '');
+          args.content = content;
+        },
+        // 指定在 WebKit 中粘贴时要保留的样式
+        paste_webkit_styles:
+          'color font font-size font-family font-weight width height margin padding line-height text-align border border-radius',
       },
     };
   },