vue-editify 0.0.34 → 0.0.36

Sign up to get free protection for your applications and to get access to all the features.
package/examples/App.vue CHANGED
@@ -1,19 +1,22 @@
1
1
  <template>
2
2
  <div style="padding: 100px 50px 50px 50px">
3
- <editify v-model="value" placeholder="请输入正文内容..." allow-paste-html border @change="change" :menu="menuConfig" ref="editify" height="400px"></editify>
3
+ <editify v-model="value" placeholder="请输入正文内容..." allow-paste-html border @change="change" :menu="menuConfig" ref="editify" height="400px" @after-render="afterRender" :paste-keep-marks="{ 'data-zip': ['span'] }" :custom-parse-node="parseNode"></editify>
4
4
  </div>
5
5
  </template>
6
6
  <script>
7
+ import { AlexElement } from '../src'
7
8
  import { h } from 'vue'
9
+ import Dap from 'dap-util'
8
10
  export default {
9
11
  name: 'App',
10
12
  data() {
11
13
  return {
12
- value: '<p><span>这是一个基于 </span><span data-editify-code="true">Vue3 + alex-editor</span><span> 构建的一套</span><span style="font-weight: bold;">精美UI样式</span><span>的</span><span style="font-weight: bold;">开箱即用</span><span>的</span><span style="color: #ec1a0a;">富文本编辑器</span></p>',
14
+ value: '<p><span>这是一个基于 </span><code>Vue3 + alex-editor</code><span> 构建的一套</span><span style="font-weight: bold;">精美UI样式</span><span>的</span><span style="font-weight: bold;">开箱即用</span><span>的</span><span style="color: #ec1a0a;">富文本编辑器</span></p>',
13
15
  menuConfig: {
14
16
  //mode: 'inner',
15
17
  sequence: {
16
- alert: 100
18
+ alert: 100,
19
+ zip: 101
17
20
  },
18
21
  table: {
19
22
  maxRows: 20,
@@ -23,6 +26,38 @@ export default {
23
26
  show: true
24
27
  },
25
28
  extends: {
29
+ zip: {
30
+ title: '上传压缩包',
31
+ default: () => {
32
+ return h('span', {}, 'zip')
33
+ },
34
+ onOperate: () => {
35
+ //选择文件上传
36
+ const upload = document.createElement('input')
37
+ upload.setAttribute('type', 'file')
38
+ upload.setAttribute('accept', 'application/zip')
39
+ upload.onchange = async e => {
40
+ //获取到文件
41
+ const file = e.currentTarget.files[0]
42
+ if (file) {
43
+ //转成base64
44
+ const base64 = await Dap.file.dataFileToBase64(file)
45
+ //创建元素
46
+ const zipEle = new AlexElement('closed', 'span', { 'data-zip': 'true', contenteditable: 'false' }, null, null)
47
+ //插入编辑器
48
+ this.$refs.editify.editor.insertElement(zipEle)
49
+ //移动光标到新插入的元素
50
+ this.$refs.editify.editor.range.anchor.moveToStart(zipEle)
51
+ this.$refs.editify.editor.range.focus.moveToStart(zipEle)
52
+ //格式化
53
+ this.$refs.editify.editor.formatElementStack()
54
+ //渲染
55
+ this.$refs.editify.editor.domRender()
56
+ }
57
+ }
58
+ upload.click()
59
+ }
60
+ },
26
61
  alert: {
27
62
  title: '自定义菜单按钮',
28
63
  leftBorder: true,
@@ -66,6 +101,23 @@ export default {
66
101
  // }, 3000)
67
102
  },
68
103
  methods: {
104
+ afterRender() {
105
+ this.$refs.editify.$el.querySelectorAll('[data-zip]').forEach(el => {
106
+ el.onclick = function () {
107
+ const url = el.getAttribute('data-zip')
108
+ const a = document.createElement('a')
109
+ a.setAttribute('href', url)
110
+ a.setAttribute('download', 'download.zip')
111
+ a.click()
112
+ }
113
+ })
114
+ },
115
+ parseNode(ele) {
116
+ if (ele.hasMarks() && ele.marks['data-zip']) {
117
+ ele.type = 'closed'
118
+ }
119
+ return ele
120
+ },
69
121
  change() {
70
122
  console.log(this.$refs.editify.textValue)
71
123
  },
@@ -88,4 +140,14 @@ body {
88
140
  height: 100%;
89
141
  overflow: auto;
90
142
  }
143
+
144
+ span[data-zip] {
145
+ display: inline-block;
146
+ width: 40px;
147
+ height: 40px;
148
+ background: url(https://www.ling0523.cn/images/image_0_1702456046669.png) no-repeat center;
149
+ background-size: cover;
150
+ cursor: pointer;
151
+ margin: 0 10px;
152
+ }
91
153
  </style>
package/lib/editify.es.js CHANGED
@@ -1844,7 +1844,9 @@ const initEditorOptions = (options) => {
1844
1844
  //自定义视频粘贴方法
1845
1845
  customVideoPaste: null,
1846
1846
  //自定义处理不可编辑元素合并的逻辑
1847
- customMerge: null
1847
+ customMerge: null,
1848
+ //自定义dom转为非文本元素的后续处理逻辑
1849
+ customParseNode: null
1848
1850
  };
1849
1851
  if (obj$1.common.isObject(options)) {
1850
1852
  if (typeof options.disabled == "boolean") {
@@ -1883,6 +1885,9 @@ const initEditorOptions = (options) => {
1883
1885
  if (typeof options.customMerge == "function") {
1884
1886
  opts.customMerge = options.customMerge;
1885
1887
  }
1888
+ if (typeof options.customParseNode == "function") {
1889
+ opts.customParseNode = options.customParseNode;
1890
+ }
1886
1891
  }
1887
1892
  return opts;
1888
1893
  };
@@ -3258,6 +3263,7 @@ class AlexEditor {
3258
3263
  this.customImagePaste = options.customImagePaste;
3259
3264
  this.customVideoPaste = options.customVideoPaste;
3260
3265
  this.customMerge = options.customMerge;
3266
+ this.customParseNode = options.customParseNode;
3261
3267
  this.useClipboard = canUseClipboard();
3262
3268
  this.history = new AlexHistory();
3263
3269
  this.stack = this.parseHtml(this.value);
@@ -4251,6 +4257,9 @@ class AlexEditor {
4251
4257
  }
4252
4258
  });
4253
4259
  }
4260
+ if (typeof this.customParseNode == "function") {
4261
+ element2 = this.customParseNode.apply(this, [element2]);
4262
+ }
4254
4263
  return element2;
4255
4264
  }
4256
4265
  /**
@@ -15387,6 +15396,21 @@ const editorProps = {
15387
15396
  menu: {
15388
15397
  type: Object,
15389
15398
  default: null
15399
+ },
15400
+ //dom转换时的额外处理
15401
+ customParseNode: {
15402
+ type: Function,
15403
+ default: null
15404
+ },
15405
+ //粘贴html时额外保留的标记(全部元素生效)
15406
+ pasteKeepMarks: {
15407
+ type: Object,
15408
+ default: null
15409
+ },
15410
+ //粘贴html时额外保留的样式(仅在非文本元素生效)
15411
+ pasteKeepStyles: {
15412
+ type: Object,
15413
+ default: null
15390
15414
  }
15391
15415
  };
15392
15416
  const getColNumbers = (row) => {
@@ -15479,19 +15503,6 @@ const parseList = function(element2) {
15479
15503
  }
15480
15504
  }
15481
15505
  };
15482
- const parseCode = function(element2) {
15483
- if (element2.parsedom == "code") {
15484
- element2.parsedom = "span";
15485
- const marks = {
15486
- "data-editify-code": true
15487
- };
15488
- if (element2.hasMarks()) {
15489
- Object.assign(element2.marks, marks);
15490
- } else {
15491
- element2.marks = marks;
15492
- }
15493
- }
15494
- };
15495
15506
  const mediaHandle = function(element2) {
15496
15507
  if (element2.parsedom == "img" || element2.parsedom == "video" || element2.parsedom == "a") {
15497
15508
  const marks = {
@@ -21186,7 +21197,7 @@ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
21186
21197
  ], 14, _hoisted_1$1);
21187
21198
  }
21188
21199
  const Menu = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1], ["__scopeId", "data-v-42f60b43"]]);
21189
- const Editify_vue_vue_type_style_index_0_scoped_237c369a_lang = "";
21200
+ const Editify_vue_vue_type_style_index_0_scoped_8415c1dc_lang = "";
21190
21201
  const _sfc_main = {
21191
21202
  name: "editify",
21192
21203
  props: { ...editorProps },
@@ -21312,7 +21323,6 @@ const _sfc_main = {
21312
21323
  disabled: this.disabled,
21313
21324
  renderRules: [
21314
21325
  parseList,
21315
- parseCode,
21316
21326
  mediaHandle,
21317
21327
  tableHandle,
21318
21328
  (el) => {
@@ -21327,7 +21337,8 @@ const _sfc_main = {
21327
21337
  allowPasteHtml: this.allowPasteHtml,
21328
21338
  customImagePaste: this.customImagePaste,
21329
21339
  customVideoPaste: this.customVideoPaste,
21330
- customMerge: this.handleCustomMerge
21340
+ customMerge: this.handleCustomMerge,
21341
+ customParseNode: this.handleCustomParseNode
21331
21342
  });
21332
21343
  this.internalModify(this.editor.value);
21333
21344
  this.editor.on("change", this.handleEditorChange);
@@ -21468,6 +21479,24 @@ const _sfc_main = {
21468
21479
  ele.children = null;
21469
21480
  }
21470
21481
  },
21482
+ //针对node转为元素进行额外的处理
21483
+ handleCustomParseNode(ele) {
21484
+ if (ele.parsedom == "code") {
21485
+ ele.parsedom = "span";
21486
+ const marks = {
21487
+ "data-editify-code": true
21488
+ };
21489
+ if (ele.hasMarks()) {
21490
+ Object.assign(ele.marks, marks);
21491
+ } else {
21492
+ ele.marks = marks;
21493
+ }
21494
+ }
21495
+ if (typeof this.customParseNode == "function") {
21496
+ ele = this.customParseNode.apply(this, [ele]);
21497
+ }
21498
+ return ele;
21499
+ },
21471
21500
  //隐藏工具条
21472
21501
  hideToolbar() {
21473
21502
  this.toolbarOptions.show = false;
@@ -21703,20 +21732,22 @@ const _sfc_main = {
21703
21732
  },
21704
21733
  //编辑器粘贴html
21705
21734
  handlePasteHtml(elements, data2) {
21735
+ const keepStyles = Object.assign(pasteKeepData.styles, this.pasteKeepStyles || {});
21736
+ const keepMarks = Object.assign(pasteKeepData.marks, this.pasteKeepMarks || {});
21706
21737
  AlexElement.flatElements(elements).forEach((el) => {
21707
21738
  let marks = {};
21708
21739
  let styles = {};
21709
21740
  if (el.hasMarks()) {
21710
- for (let key in pasteKeepData.marks) {
21711
- if (el.marks.hasOwnProperty(key) && (Array.isArray(pasteKeepData.marks[key]) && pasteKeepData.marks[key].includes(el.parsedom) || pasteKeepData.marks[key] == "*")) {
21741
+ for (let key in keepMarks) {
21742
+ if (el.marks.hasOwnProperty(key) && (Array.isArray(keepMarks[key]) && keepMarks[key].includes(el.parsedom) || keepMarks[key] == "*")) {
21712
21743
  marks[key] = el.marks[key];
21713
21744
  }
21714
21745
  }
21715
21746
  el.marks = marks;
21716
21747
  }
21717
21748
  if (el.hasStyles() && !el.isText()) {
21718
- for (let key in pasteKeepData.styles) {
21719
- if (el.styles.hasOwnProperty(key) && (Array.isArray(pasteKeepData.styles[key]) && pasteKeepData.styles[key].includes(el.parsedom) || pasteKeepData.styles[key] == "*")) {
21749
+ for (let key in keepStyles) {
21750
+ if (el.styles.hasOwnProperty(key) && (Array.isArray(keepStyles[key]) && keepStyles[key].includes(el.parsedom) || keepStyles[key] == "*")) {
21720
21751
  styles[key] = el.styles[key];
21721
21752
  }
21722
21753
  }
@@ -22783,7 +22814,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
22783
22814
  ])) : createCommentVNode("", true)
22784
22815
  ]);
22785
22816
  }
22786
- const Editify = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-237c369a"]]);
22817
+ const Editify = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-8415c1dc"]]);
22787
22818
  const iconfont = "";
22788
22819
  const en_US = {
22789
22820
  textWrapUp: "Up feed",
@@ -22962,7 +22993,7 @@ const i18n = (locale) => {
22962
22993
  return translations[locale][key];
22963
22994
  };
22964
22995
  };
22965
- const version = "0.0.34";
22996
+ const version = "0.0.36";
22966
22997
  const install = (app, props) => {
22967
22998
  const locale = (props ? props.locale : "zh_CN") || "zh_CN";
22968
22999
  app.provide("$editTrans", i18n(locale));