vue-editify 0.1.13 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/editify.es.js CHANGED
@@ -1146,6 +1146,151 @@ const event$1 = {
1146
1146
  return events;
1147
1147
  }
1148
1148
  };
1149
+ const file$1 = {
1150
+ /**
1151
+ * 根据文件获取可预览的图片路径
1152
+ * @param {Object} file
1153
+ */
1154
+ getImageUrl(file2) {
1155
+ if (!file2 || !(file2 instanceof File)) {
1156
+ throw new TypeError("The argument must be a File object");
1157
+ }
1158
+ return window.URL.createObjectURL(file2);
1159
+ },
1160
+ /**
1161
+ * 将JS的file对象转为BASE64位字符串,通过then方法回调,参数为base64字符串
1162
+ * @param {Object} file
1163
+ */
1164
+ dataFileToBase64(file2) {
1165
+ return new Promise((resolve, reject) => {
1166
+ if (!file2 || !(file2 instanceof File)) {
1167
+ reject(new TypeError("The argument must be a File object"));
1168
+ }
1169
+ let reader = new FileReader();
1170
+ reader.readAsDataURL(file2);
1171
+ reader.onloadend = () => {
1172
+ let dataURL = reader.result;
1173
+ resolve(dataURL);
1174
+ };
1175
+ });
1176
+ },
1177
+ /**
1178
+ * 将base64位格式文件转换为file对象
1179
+ * @param {Object} base64String base64位格式字符串
1180
+ * @param {Object} fileName 转换后的文件名字,包含后缀
1181
+ */
1182
+ dataBase64toFile(base64String, fileName) {
1183
+ if (!base64String || typeof base64String != "string") {
1184
+ throw new TypeError("The first argument must be a string");
1185
+ }
1186
+ if (!fileName || typeof fileName != "string") {
1187
+ throw new TypeError("The second argument must be a string");
1188
+ }
1189
+ let arr = base64String.split(",");
1190
+ let mime = arr[0].match(/:(.*?);/)[1];
1191
+ let bstr = atob(arr[1]);
1192
+ let n = bstr.length;
1193
+ let u8arr = new Uint8Array(n);
1194
+ while (n--) {
1195
+ u8arr[n] = bstr.charCodeAt(n);
1196
+ }
1197
+ return new File([u8arr], fileName, {
1198
+ type: mime
1199
+ });
1200
+ },
1201
+ /**
1202
+ * 图片压缩方法
1203
+ * @param {*} file 需要压缩的图片File文件
1204
+ * @param {*} opts 压缩参数
1205
+ */
1206
+ compressImage(file2, opts) {
1207
+ const options = {
1208
+ //压缩图片的宽,单位px,如果不设置默认为原图宽
1209
+ width: void 0,
1210
+ //压缩图片质量,默认为原图的0.8
1211
+ quality: 0.8,
1212
+ //图片类型,jpeg或者webp,默认为jpeg
1213
+ mimeType: "jpeg",
1214
+ //压缩后的最大值,单位kb,默认为0表示不设置此值
1215
+ maxSize: 0,
1216
+ //小于该大小的图片不进行压缩,单位kb,默认为0表示任何图片都要压缩
1217
+ minSize: 0
1218
+ };
1219
+ if (common$1.isObject(opts)) {
1220
+ if (number$1.isNumber(opts.width)) {
1221
+ options.width = opts.width;
1222
+ }
1223
+ if (number$1.isNumber(opts.quality) && opts.quality >= 0 && opts.quality <= 1) {
1224
+ options.quality = opts.quality;
1225
+ }
1226
+ if (opts.mimeType == "jpeg" || opts.mimeType == "webp") {
1227
+ options.mimeType = opts.mimeType;
1228
+ }
1229
+ if (number$1.isNumber(opts.maxSize)) {
1230
+ options.maxSize = opts.maxSize;
1231
+ }
1232
+ if (number$1.isNumber(opts.minSize)) {
1233
+ options.minSize = opts.minSize;
1234
+ }
1235
+ }
1236
+ const createFile = (canvas, fileName, quality) => {
1237
+ let url = canvas.toDataURL("image/" + options.mimeType, quality);
1238
+ let file22 = this.dataBase64toFile(url, fileName);
1239
+ if (options.maxSize > 0 && file22.size > options.maxSize * 1024) {
1240
+ quality = quality <= 0 ? 0 : Number((quality - 0.01).toFixed(2));
1241
+ const res = createFile(canvas, fileName, quality);
1242
+ url = res.url;
1243
+ file22 = res.file;
1244
+ quality = res.quality;
1245
+ }
1246
+ return {
1247
+ file: file22,
1248
+ url,
1249
+ quality
1250
+ };
1251
+ };
1252
+ return new Promise((resolve, reject) => {
1253
+ let reader = new FileReader();
1254
+ reader.readAsDataURL(file2);
1255
+ reader.onload = () => {
1256
+ let url = reader.result;
1257
+ let img = new Image();
1258
+ img.src = url;
1259
+ img.onload = () => {
1260
+ if (options.minSize > 0 && file2.size <= options.minSize * 1024) {
1261
+ resolve({
1262
+ file: file2,
1263
+ url,
1264
+ quality: 1,
1265
+ width: img.width,
1266
+ height: img.height
1267
+ });
1268
+ return;
1269
+ }
1270
+ let canvas = document.createElement("canvas");
1271
+ let context = canvas.getContext("2d");
1272
+ canvas.width = options.width || img.width;
1273
+ canvas.height = options.width ? options.width / (img.width / img.height) : img.height;
1274
+ context.drawImage(img, 0, 0, canvas.width, canvas.height);
1275
+ let index = file2.name.lastIndexOf(".");
1276
+ const fileName = file2.name.substring(0, index) + "." + options.mimeType;
1277
+ let res = createFile(canvas, fileName, options.quality);
1278
+ resolve({
1279
+ ...res,
1280
+ width: canvas.width,
1281
+ height: canvas.height
1282
+ });
1283
+ };
1284
+ img.onerror = () => {
1285
+ reject(new Error("Failed to load image file"));
1286
+ };
1287
+ };
1288
+ reader.onerror = () => {
1289
+ reject(new Error("Failed to load image file"));
1290
+ };
1291
+ });
1292
+ }
1293
+ };
1149
1294
  const platform = {
1150
1295
  //设备语言类型
1151
1296
  language() {
@@ -1349,15 +1494,6 @@ const isContains = function(parentNode, childNode) {
1349
1494
  }
1350
1495
  return element$1.isContains(parentNode, childNode);
1351
1496
  };
1352
- const blobToBase64 = function(blob) {
1353
- return new Promise((resolve) => {
1354
- const fileReader = new FileReader();
1355
- fileReader.onload = (e) => {
1356
- resolve(e.target.result);
1357
- };
1358
- fileReader.readAsDataURL(blob);
1359
- });
1360
- };
1361
1497
  const canUseClipboard = function() {
1362
1498
  if (!window.ClipboardItem) {
1363
1499
  console.warn("window.ClipboardItem must be obtained in a secure environment, such as localhost, 127.0.0.1, or https, so the editor's copy, paste, and cut functions cannot be used");
@@ -1395,6 +1531,7 @@ const initEditorOptions = function(options) {
1395
1531
  customHtmlPaste: null,
1396
1532
  customImagePaste: null,
1397
1533
  customVideoPaste: null,
1534
+ customFilePaste: null,
1398
1535
  customMerge: null,
1399
1536
  customParseNode: null
1400
1537
  };
@@ -1432,6 +1569,9 @@ const initEditorOptions = function(options) {
1432
1569
  if (typeof options.customVideoPaste == "function") {
1433
1570
  opts.customVideoPaste = options.customVideoPaste;
1434
1571
  }
1572
+ if (typeof options.customFilePaste == "function") {
1573
+ opts.customFilePaste = options.customFilePaste;
1574
+ }
1435
1575
  if (typeof options.customMerge == "function") {
1436
1576
  opts.customMerge = options.customMerge;
1437
1577
  }
@@ -2805,18 +2945,126 @@ const handleCut = async function(e) {
2805
2945
  this.rangeRender();
2806
2946
  }
2807
2947
  };
2948
+ const doPaste = async function(html, text, files) {
2949
+ if (html) {
2950
+ if (this.allowPasteHtml) {
2951
+ const elements = this.parseHtml(html).filter((el) => {
2952
+ return !el.isEmpty();
2953
+ });
2954
+ if (typeof this.customHtmlPaste == "function") {
2955
+ await this.customHtmlPaste.apply(this, [elements, html]);
2956
+ } else {
2957
+ for (let i = 0; i < elements.length; i++) {
2958
+ this.insertElement(elements[i], false);
2959
+ }
2960
+ this.emit("pasteHtml", elements, html);
2961
+ }
2962
+ } else if (text) {
2963
+ if (typeof this.customTextPaste == "function") {
2964
+ await this.customTextPaste.apply(this, [text]);
2965
+ } else {
2966
+ this.insertText(text);
2967
+ this.emit("pasteText", text);
2968
+ }
2969
+ }
2970
+ } else {
2971
+ if (text) {
2972
+ if (typeof this.customTextPaste == "function") {
2973
+ await this.customTextPaste.apply(this, [text]);
2974
+ } else {
2975
+ this.insertText(text);
2976
+ this.emit("pasteText", text);
2977
+ }
2978
+ } else {
2979
+ let length = files.length;
2980
+ for (let i = 0; i < length; i++) {
2981
+ const url = await file$1.dataFileToBase64(files[i]);
2982
+ if (files[i].type.startsWith("image/")) {
2983
+ if (typeof this.customImagePaste == "function") {
2984
+ await this.customImagePaste.apply(this, [url]);
2985
+ } else {
2986
+ const image = new AlexElement(
2987
+ "closed",
2988
+ "img",
2989
+ {
2990
+ src: url
2991
+ },
2992
+ null,
2993
+ null
2994
+ );
2995
+ this.insertElement(image);
2996
+ this.emit("pasteImage", url);
2997
+ }
2998
+ } else if (files[i].type.startsWith("video/")) {
2999
+ if (typeof this.customVideoPaste == "function") {
3000
+ await this.customVideoPaste.apply(this, [url]);
3001
+ } else {
3002
+ const video = new AlexElement(
3003
+ "closed",
3004
+ "video",
3005
+ {
3006
+ src: url
3007
+ },
3008
+ null,
3009
+ null
3010
+ );
3011
+ this.insertElement(video);
3012
+ this.emit("pasteVideo", url);
3013
+ }
3014
+ } else {
3015
+ if (typeof this.customFilePaste == "function") {
3016
+ await this.customFilePaste.apply(this, [url]);
3017
+ }
3018
+ }
3019
+ }
3020
+ }
3021
+ }
3022
+ };
2808
3023
  const handlePaste = async function(e) {
2809
3024
  e.preventDefault();
2810
3025
  if (this.disabled) {
2811
3026
  return;
2812
3027
  }
2813
- await this.paste();
2814
- this.formatElementStack();
2815
- this.domRender();
2816
- this.rangeRender();
3028
+ if (!this.range) {
3029
+ return;
3030
+ }
3031
+ if (!this.allowPaste) {
3032
+ return;
3033
+ }
3034
+ const event2 = e;
3035
+ if (event2.clipboardData) {
3036
+ const html = event2.clipboardData.getData("text/html");
3037
+ const text = event2.clipboardData.getData("text/plain");
3038
+ const files = event2.clipboardData.files;
3039
+ await doPaste.apply(this, [html, text, files]);
3040
+ this.formatElementStack();
3041
+ this.domRender();
3042
+ this.rangeRender();
3043
+ }
2817
3044
  };
2818
- const handleDragDrop = function(e) {
3045
+ const handleDragDrop = async function(e) {
2819
3046
  e.preventDefault();
3047
+ if (e.type == "drop") {
3048
+ if (this.disabled) {
3049
+ return;
3050
+ }
3051
+ if (!this.range) {
3052
+ return;
3053
+ }
3054
+ if (!this.allowPaste) {
3055
+ return;
3056
+ }
3057
+ const event2 = e;
3058
+ if (event2.dataTransfer) {
3059
+ const html = event2.dataTransfer.getData("text/html");
3060
+ const text = event2.dataTransfer.getData("text/plain");
3061
+ const files = event2.dataTransfer.files;
3062
+ await doPaste.apply(this, [html, text, files]);
3063
+ this.formatElementStack();
3064
+ this.domRender();
3065
+ this.rangeRender();
3066
+ }
3067
+ }
2820
3068
  };
2821
3069
  const handleFocus = function() {
2822
3070
  if (this.disabled) {
@@ -2844,6 +3092,7 @@ class AlexEditor {
2844
3092
  __publicField(this, "customHtmlPaste");
2845
3093
  __publicField(this, "customImagePaste");
2846
3094
  __publicField(this, "customVideoPaste");
3095
+ __publicField(this, "customFilePaste");
2847
3096
  __publicField(this, "customMerge");
2848
3097
  __publicField(this, "customParseNode");
2849
3098
  __publicField(this, "useClipboard", canUseClipboard());
@@ -2869,6 +3118,7 @@ class AlexEditor {
2869
3118
  this.customHtmlPaste = options.customHtmlPaste;
2870
3119
  this.customImagePaste = options.customImagePaste;
2871
3120
  this.customVideoPaste = options.customVideoPaste;
3121
+ this.customFilePaste = options.customFilePaste;
2872
3122
  this.customMerge = options.customMerge;
2873
3123
  this.customParseNode = options.customParseNode;
2874
3124
  this.stack = this.parseHtml(this.value);
@@ -2881,7 +3131,7 @@ class AlexEditor {
2881
3131
  event$1.on(this.$el, "cut.alex_editor", handleCut.bind(this));
2882
3132
  event$1.on(this.$el, "paste.alex_editor", handlePaste.bind(this));
2883
3133
  event$1.on(this.$el, "copy.alex_editor", handleCopy.bind(this));
2884
- event$1.on(this.$el, "dragstart.alex_editor drop.alex_editor ", handleDragDrop.bind(this));
3134
+ event$1.on(this.$el, "dragstart.alex_editor drop.alex_editor", handleDragDrop.bind(this));
2885
3135
  event$1.on(this.$el, "focus.alex_editor", handleFocus.bind(this));
2886
3136
  event$1.on(this.$el, "blur.alex_editor", handleBlur.bind(this));
2887
3137
  }
@@ -2958,114 +3208,6 @@ class AlexEditor {
2958
3208
  }
2959
3209
  return result;
2960
3210
  }
2961
- /**
2962
- * 根据光标进行粘贴操作
2963
- */
2964
- async paste() {
2965
- if (this.disabled) {
2966
- return;
2967
- }
2968
- if (!this.range) {
2969
- return;
2970
- }
2971
- if (!this.useClipboard) {
2972
- return;
2973
- }
2974
- if (!this.allowPaste) {
2975
- return;
2976
- }
2977
- const clipboardItems = await navigator.clipboard.read();
2978
- const clipboardItem = clipboardItems[0];
2979
- const getTypeFunctions = [];
2980
- clipboardItem.types.forEach((type) => {
2981
- getTypeFunctions.push(clipboardItem.getType(type));
2982
- });
2983
- const blobs = await Promise.all(getTypeFunctions);
2984
- const length = blobs.length;
2985
- const hasHtml = blobs.some((blob) => {
2986
- return blob.type == "text/html";
2987
- });
2988
- if (hasHtml) {
2989
- for (let i = 0; i < length; i++) {
2990
- const blob = blobs[i];
2991
- if (blob.type == "text/plain" && !this.allowPasteHtml) {
2992
- const data2 = await blob.text();
2993
- if (data2) {
2994
- if (typeof this.customTextPaste == "function") {
2995
- await this.customTextPaste.apply(this, [data2]);
2996
- } else {
2997
- this.insertText(data2);
2998
- this.emit("pasteText", data2);
2999
- }
3000
- }
3001
- } else if (blob.type == "text/html" && this.allowPasteHtml) {
3002
- const data2 = await blob.text();
3003
- if (data2) {
3004
- const elements = this.parseHtml(data2).filter((el) => {
3005
- return !el.isEmpty();
3006
- });
3007
- if (typeof this.customHtmlPaste == "function") {
3008
- await this.customHtmlPaste.apply(this, [elements, data2]);
3009
- } else {
3010
- for (let i2 = 0; i2 < elements.length; i2++) {
3011
- this.insertElement(elements[i2], false);
3012
- }
3013
- this.emit("pasteHtml", elements, data2);
3014
- }
3015
- }
3016
- }
3017
- }
3018
- } else {
3019
- for (let i = 0; i < length; i++) {
3020
- const blob = blobs[i];
3021
- if (blob.type.startsWith("image/")) {
3022
- const url = await blobToBase64(blob);
3023
- if (typeof this.customImagePaste == "function") {
3024
- await this.customImagePaste.apply(this, [url]);
3025
- } else {
3026
- const image = new AlexElement(
3027
- "closed",
3028
- "img",
3029
- {
3030
- src: url
3031
- },
3032
- null,
3033
- null
3034
- );
3035
- this.insertElement(image);
3036
- this.emit("pasteImage", url);
3037
- }
3038
- } else if (blob.type.startsWith("video/")) {
3039
- const url = await blobToBase64(blob);
3040
- if (typeof this.customVideoPaste == "function") {
3041
- await this.customVideoPaste.apply(this, [url]);
3042
- } else {
3043
- const video = new AlexElement(
3044
- "closed",
3045
- "video",
3046
- {
3047
- src: url
3048
- },
3049
- null,
3050
- null
3051
- );
3052
- this.insertElement(video);
3053
- this.emit("pasteVideo", url);
3054
- }
3055
- } else if (blob.type == "text/plain") {
3056
- const data2 = await blob.text();
3057
- if (data2) {
3058
- if (typeof this.customTextPaste == "function") {
3059
- await this.customTextPaste.apply(this, [data2]);
3060
- } else {
3061
- this.insertText(data2);
3062
- this.emit("pasteText", data2);
3063
- }
3064
- }
3065
- }
3066
- }
3067
- }
3068
- }
3069
3211
  /**
3070
3212
  * 根据光标进行删除操作
3071
3213
  */
@@ -19655,6 +19797,15 @@ const tableHandle = function(editor, element2) {
19655
19797
  } else {
19656
19798
  element2.marks = marks;
19657
19799
  }
19800
+ const styles = {
19801
+ "white-space": "pre-wrap",
19802
+ "word-break": "break-word"
19803
+ };
19804
+ if (element2.hasStyles()) {
19805
+ Object.assign(element2.styles, styles);
19806
+ } else {
19807
+ element2.styles = styles;
19808
+ }
19658
19809
  const elements = AlexElement.flatElements(element2.children);
19659
19810
  const rows = elements.filter((el) => {
19660
19811
  return el.parsedom == "tr";
@@ -20528,7 +20679,8 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
20528
20679
  "show-triangle": "",
20529
20680
  color: "#fff",
20530
20681
  placement: "bottom",
20531
- animation: "fade"
20682
+ animation: "fade",
20683
+ "z-index": 10
20532
20684
  }, {
20533
20685
  default: withCtx(() => [
20534
20686
  createElementVNode("div", _hoisted_1$a, toDisplayString(_ctx.content), 1)
@@ -20539,7 +20691,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
20539
20691
  };
20540
20692
  }
20541
20693
  });
20542
- const Tooltip = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-638bc915"]]);
20694
+ const Tooltip = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-8372de0b"]]);
20543
20695
  const IconProps = {
20544
20696
  //图标值
20545
20697
  value: {
@@ -21896,7 +22048,8 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
21896
22048
  border: "",
21897
22049
  placement: "bottom-start",
21898
22050
  onShow: layerShow,
21899
- useRange: _ctx.type == "text"
22051
+ useRange: _ctx.type == "text",
22052
+ "z-index": 10
21900
22053
  }, {
21901
22054
  default: withCtx(() => [
21902
22055
  createElementVNode("div", {
@@ -22608,7 +22761,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
22608
22761
  };
22609
22762
  }
22610
22763
  });
22611
- const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-23266de7"]]);
22764
+ const Toolbar = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-44b03ca9"]]);
22612
22765
  const InsertLinkProps = {
22613
22766
  //主题色
22614
22767
  color: {
@@ -24558,7 +24711,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
24558
24711
  };
24559
24712
  }
24560
24713
  });
24561
- const Menu = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-e2dd8748"]]);
24714
+ const Menu = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-226bbacd"]]);
24562
24715
  const EditifyProps = {
24563
24716
  //国际化语言类型
24564
24717
  locale: {
@@ -24643,6 +24796,11 @@ const EditifyProps = {
24643
24796
  type: Function,
24644
24797
  default: null
24645
24798
  },
24799
+ //自定义粘贴文件
24800
+ customFilePaste: {
24801
+ type: Function,
24802
+ default: null
24803
+ },
24646
24804
  //菜单栏配置
24647
24805
  menu: {
24648
24806
  type: Object,
@@ -25066,8 +25224,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
25066
25224
  allowPaste: props.allowPaste,
25067
25225
  allowCut: props.allowCut,
25068
25226
  allowPasteHtml: props.allowPasteHtml,
25069
- customImagePaste: handleCustomImagePaste,
25070
- customVideoPaste: handleCustomVideoPaste,
25227
+ customImagePaste: props.customImagePaste,
25228
+ customVideoPaste: props.customVideoPaste,
25229
+ customFilePaste: props.customFilePaste,
25071
25230
  customMerge: handleCustomMerge,
25072
25231
  customParseNode: handleCustomParseNode
25073
25232
  });
@@ -25197,18 +25356,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
25197
25356
  }
25198
25357
  }
25199
25358
  };
25200
- const handleCustomImagePaste = async (url) => {
25201
- const newUrl = await props.customImagePaste.apply(instance.proxy, [url]);
25202
- if (newUrl) {
25203
- insertImage(editor.value, newUrl);
25204
- }
25205
- };
25206
- const handleCustomVideoPaste = async (url) => {
25207
- const newUrl = await props.customVideoPaste.apply(instance.proxy, [url]);
25208
- if (newUrl) {
25209
- insertVideo(editor.value, newUrl);
25210
- }
25211
- };
25212
25359
  const handleCustomMerge = (ele, preEle) => {
25213
25360
  const uneditable = preEle.getUneditableElement();
25214
25361
  if (uneditable) {
@@ -25569,8 +25716,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
25569
25716
  };
25570
25717
  }
25571
25718
  });
25572
- const Editify = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-99f85ef5"]]);
25573
- const version = "0.1.13";
25719
+ const Editify = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-fed58116"]]);
25720
+ const version = "0.1.16";
25574
25721
  const install = (app) => {
25575
25722
  app.component(Editify.name, Editify);
25576
25723
  };