vue-editify 0.1.36 → 0.1.37

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/examples/App.vue CHANGED
@@ -6,7 +6,7 @@
6
6
  <script setup lang="ts">
7
7
  import { h, ref } from 'vue'
8
8
  import { AlexElement, MenuConfigType, Editify, attachment, PluginType } from '../src/index'
9
- const val = ref<string>('<p><br></p>')
9
+ const val = ref<string>('<p><span data-editify-attachment="xxxxx" ></span></p>')
10
10
  const editify = ref<InstanceType<typeof Editify> | null>(null)
11
11
  const menuConfig = ref<MenuConfigType>({
12
12
  use: true,
@@ -25,6 +25,7 @@ const menuConfig = ref<MenuConfigType>({
25
25
  const plugins = ref<PluginType[]>([
26
26
  attachment({
27
27
  multiple: true,
28
+ leftBorder: true,
28
29
  customUpload: (files: File[]) => {
29
30
  return files.map(item => {
30
31
  return 'xxx'
@@ -308,3 +308,10 @@ export declare const insertTable: (editor: AlexEditor, rowLength: number, colLen
308
308
  * @returns
309
309
  */
310
310
  export declare const insertCodeBlock: (editor: AlexEditor, dataRangeCaches: AlexElementsRangeType) => void;
311
+ /**
312
+ * 插入分隔线
313
+ * @param editor
314
+ * @param dataRangeCaches
315
+ * @returns
316
+ */
317
+ export declare const insertSeparator: (editor: AlexEditor) => void;
@@ -14,11 +14,11 @@ export declare const parseList: (editor: AlexEditor, element: AlexElement) => vo
14
14
  */
15
15
  export declare const orderdListHandle: (editor: AlexEditor, element: AlexElement) => void;
16
16
  /**
17
- * 元素格式化时处理媒体元素和链接
17
+ * 元素格式化时处理常规元素(图片、视频、分隔线、行内代码)
18
18
  * @param editor
19
19
  * @param element
20
20
  */
21
- export declare const mediaHandle: (editor: AlexEditor, element: AlexElement) => void;
21
+ export declare const commonElementHandle: (editor: AlexEditor, element: AlexElement) => void;
22
22
  /**
23
23
  * 元素格式化时处理表格
24
24
  * @param editor
@@ -150,6 +150,7 @@ export type MenuConfigType = {
150
150
  heading?: MenuDisplayButtonType;
151
151
  indent?: MenuSelectButtonType;
152
152
  quote?: MenuButtonType;
153
+ separator?: MenuButtonType;
153
154
  align?: MenuSelectButtonType;
154
155
  orderList?: MenuButtonType;
155
156
  unorderList?: MenuButtonType;
package/lib/editify.es.js CHANGED
@@ -3194,7 +3194,7 @@ class AlexEditor {
3194
3194
  event$1.on(this.$el, "blur.alex_editor", handleBlur.bind(this));
3195
3195
  }
3196
3196
  /**
3197
- * 初始化range
3197
+ * 初始化设置默认的range
3198
3198
  */
3199
3199
  initRange() {
3200
3200
  const elements = AlexElement.flatElements(this.stack).filter((el) => {
@@ -4520,7 +4520,7 @@ class AlexEditor {
4520
4520
  event$1.off(this.$el, "beforeinput.alex_editor compositionstart.alex_editor compositionupdate.alex_editor compositionend.alex_editor keydown.alex_editor cut.alex_editor paste.alex_editor copy.alex_editor dragstart.alex_editor drop.alex_editor focus.alex_editor blur.alex_editor");
4521
4521
  }
4522
4522
  }
4523
- const version$2 = "1.3.36";
4523
+ const version$2 = "1.3.37";
4524
4524
  console.log(`%c alex-editor %c v${version$2} `, "padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold;", "padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e; font-weight: bold;");
4525
4525
  const number = {
4526
4526
  /**
@@ -18393,30 +18393,31 @@ const getMenuConfig = function(editTrans, editLocale) {
18393
18393
  heading: 2,
18394
18394
  indent: 3,
18395
18395
  quote: 4,
18396
- align: 5,
18397
- orderList: 6,
18398
- unorderList: 7,
18399
- task: 8,
18400
- bold: 9,
18401
- underline: 10,
18402
- italic: 11,
18403
- strikethrough: 12,
18404
- code: 13,
18405
- super: 14,
18406
- sub: 15,
18407
- formatClear: 16,
18408
- fontSize: 17,
18409
- fontFamily: 18,
18410
- lineHeight: 19,
18411
- foreColor: 20,
18412
- backColor: 21,
18413
- link: 22,
18414
- image: 23,
18415
- video: 24,
18416
- table: 25,
18417
- codeBlock: 26,
18418
- sourceView: 27,
18419
- fullScreen: 28
18396
+ separator: 5,
18397
+ align: 6,
18398
+ orderList: 7,
18399
+ unorderList: 8,
18400
+ task: 9,
18401
+ bold: 10,
18402
+ underline: 11,
18403
+ italic: 12,
18404
+ strikethrough: 13,
18405
+ code: 14,
18406
+ super: 15,
18407
+ sub: 16,
18408
+ formatClear: 17,
18409
+ fontSize: 18,
18410
+ fontFamily: 19,
18411
+ lineHeight: 20,
18412
+ foreColor: 21,
18413
+ backColor: 22,
18414
+ link: 23,
18415
+ image: 24,
18416
+ video: 25,
18417
+ table: 26,
18418
+ codeBlock: 27,
18419
+ sourceView: 28,
18420
+ fullScreen: 29
18420
18421
  },
18421
18422
  //撤销按钮配置
18422
18423
  undo: {
@@ -18468,7 +18469,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18468
18469
  //右侧边框是否显示
18469
18470
  rightBorder: false
18470
18471
  },
18471
- //引用按钮配置
18472
+ //引用
18472
18473
  quote: {
18473
18474
  //是否显示此按钮
18474
18475
  show: true,
@@ -18477,6 +18478,15 @@ const getMenuConfig = function(editTrans, editLocale) {
18477
18478
  //右侧边框是否显示
18478
18479
  rightBorder: false
18479
18480
  },
18481
+ //分隔线
18482
+ separator: {
18483
+ //是否显示此按钮
18484
+ show: true,
18485
+ //左侧边框是否显示
18486
+ leftBorder: false,
18487
+ //右侧边框是否显示
18488
+ rightBorder: false
18489
+ },
18480
18490
  //对齐方式
18481
18491
  align: {
18482
18492
  //是否显示此工具
@@ -18492,7 +18502,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18492
18502
  //右侧边框是否显示
18493
18503
  rightBorder: false
18494
18504
  },
18495
- //有序列表按钮配置
18505
+ //有序列表
18496
18506
  orderList: {
18497
18507
  //是否显示此按钮
18498
18508
  show: true,
@@ -18501,7 +18511,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18501
18511
  //右侧边框是否显示
18502
18512
  rightBorder: false
18503
18513
  },
18504
- //无序列表按钮配置
18514
+ //无序列表
18505
18515
  unorderList: {
18506
18516
  //是否显示此按钮
18507
18517
  show: true,
@@ -18510,7 +18520,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18510
18520
  //右侧边框是否显示
18511
18521
  rightBorder: false
18512
18522
  },
18513
- //任务列表按钮配置
18523
+ //任务列表
18514
18524
  task: {
18515
18525
  //是否显示此按钮
18516
18526
  show: true,
@@ -18519,7 +18529,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18519
18529
  //右侧边框是否显示
18520
18530
  rightBorder: false
18521
18531
  },
18522
- //粗体按钮配置
18532
+ //粗体
18523
18533
  bold: {
18524
18534
  //是否显示此按钮
18525
18535
  show: true,
@@ -18528,7 +18538,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18528
18538
  //右侧边框是否显示
18529
18539
  rightBorder: false
18530
18540
  },
18531
- //下划线按钮配置
18541
+ //下划线
18532
18542
  underline: {
18533
18543
  //是否显示此按钮
18534
18544
  show: true,
@@ -18537,7 +18547,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18537
18547
  //右侧边框是否显示
18538
18548
  rightBorder: false
18539
18549
  },
18540
- //斜体按钮配置
18550
+ //斜体
18541
18551
  italic: {
18542
18552
  //是否显示此按钮
18543
18553
  show: true,
@@ -18546,7 +18556,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18546
18556
  //右侧边框是否显示
18547
18557
  rightBorder: false
18548
18558
  },
18549
- //删除线按钮配置
18559
+ //删除线
18550
18560
  strikethrough: {
18551
18561
  //是否显示此按钮
18552
18562
  show: true,
@@ -18555,7 +18565,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18555
18565
  //右侧边框是否显示
18556
18566
  rightBorder: false
18557
18567
  },
18558
- //行内代码按钮配置
18568
+ //行内代码
18559
18569
  code: {
18560
18570
  //是否显示此按钮
18561
18571
  show: true,
@@ -18742,7 +18752,7 @@ const getMenuConfig = function(editTrans, editLocale) {
18742
18752
  //是否显示此工具
18743
18753
  show: false,
18744
18754
  //左侧边框是否显示
18745
- leftBorder: false,
18755
+ leftBorder: true,
18746
18756
  //右侧边框是否显示
18747
18757
  rightBorder: false
18748
18758
  },
@@ -19709,6 +19719,19 @@ const insertCodeBlock = (editor, dataRangeCaches) => {
19709
19719
  }
19710
19720
  }
19711
19721
  };
19722
+ const insertSeparator = (editor) => {
19723
+ if (!editor.range) {
19724
+ return;
19725
+ }
19726
+ const separator = new AlexElement("closed", "hr", null, null, null);
19727
+ editor.insertElement(separator);
19728
+ const leftSpace = AlexElement.getSpaceElement();
19729
+ const rightSpace = AlexElement.getSpaceElement();
19730
+ editor.addElementAfter(rightSpace, separator);
19731
+ editor.addElementBefore(leftSpace, separator);
19732
+ editor.range.anchor.moveToEnd(rightSpace);
19733
+ editor.range.focus.moveToEnd(rightSpace);
19734
+ };
19712
19735
  const updateRangeInPre = (editor, element2, originalTextElements, newElements) => {
19713
19736
  if (!editor.range) {
19714
19737
  return;
@@ -19755,10 +19778,13 @@ const parseList = (editor, element2) => {
19755
19778
  const newEl = el.clone();
19756
19779
  newEl.parsedom = "div";
19757
19780
  newEl.type = element2.type;
19758
- if (!newEl.hasMarks()) {
19759
- newEl.marks = {};
19781
+ if (newEl.hasMarks()) {
19782
+ newEl.marks["data-editify-list"] = element2.parsedom;
19783
+ } else {
19784
+ newEl.marks = {
19785
+ "data-editify-list": element2.parsedom
19786
+ };
19760
19787
  }
19761
- newEl.marks["data-editify-list"] = element2.parsedom;
19762
19788
  editor.addElementBefore(newEl, element2);
19763
19789
  });
19764
19790
  }
@@ -19776,7 +19802,7 @@ const orderdListHandle = function(editor, element2) {
19776
19802
  }
19777
19803
  }
19778
19804
  };
19779
- const mediaHandle = function(editor, element2) {
19805
+ const commonElementHandle = function(editor, element2) {
19780
19806
  if (element2.parsedom == "img" || element2.parsedom == "video" || element2.parsedom == "a") {
19781
19807
  const marks = {
19782
19808
  "data-editify-element": element2.key
@@ -19787,18 +19813,29 @@ const mediaHandle = function(editor, element2) {
19787
19813
  element2.marks = marks;
19788
19814
  }
19789
19815
  }
19790
- if (element2.parsedom == "video") {
19816
+ if (element2.parsedom == "video" || element2.parsedom == "hr") {
19791
19817
  const previousElement = editor.getPreviousElement(element2);
19792
19818
  const newTextElement = editor.getNextElement(element2);
19793
- if (!previousElement || previousElement.isEmpty()) {
19819
+ if (!previousElement || !previousElement.isSpaceText()) {
19794
19820
  const spaceText = AlexElement.getSpaceElement();
19795
19821
  editor.addElementBefore(spaceText, element2);
19796
19822
  }
19797
- if (!newTextElement || newTextElement.isEmpty()) {
19823
+ if (!newTextElement || !newTextElement.isSpaceText()) {
19798
19824
  const spaceText = AlexElement.getSpaceElement();
19799
19825
  editor.addElementAfter(spaceText, element2);
19800
19826
  }
19801
19827
  }
19828
+ if (element2.parsedom == "code") {
19829
+ element2.parsedom = "span";
19830
+ const marks = {
19831
+ "data-editify-code": true
19832
+ };
19833
+ if (element2.hasMarks()) {
19834
+ Object.assign(element2.marks, marks);
19835
+ } else {
19836
+ element2.marks = marks;
19837
+ }
19838
+ }
19802
19839
  };
19803
19840
  const tableHandle = function(editor, element2) {
19804
19841
  if (element2.parsedom == "table") {
@@ -23465,6 +23502,13 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
23465
23502
  active: false,
23466
23503
  disabled: false
23467
23504
  });
23505
+ const separatorConfig = ref({
23506
+ show: props.config.separator.show,
23507
+ leftBorder: props.config.separator.leftBorder,
23508
+ rightBorder: props.config.separator.rightBorder,
23509
+ active: false,
23510
+ disabled: false
23511
+ });
23468
23512
  const alignConfig = ref({
23469
23513
  show: props.config.align.show,
23470
23514
  selectConfig: {
@@ -23764,6 +23808,11 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
23764
23808
  editor.value.formatElementStack();
23765
23809
  editor.value.domRender();
23766
23810
  editor.value.rangeRender();
23811
+ } else if (name == "separator") {
23812
+ insertSeparator(editor.value);
23813
+ editor.value.formatElementStack();
23814
+ editor.value.domRender();
23815
+ editor.value.rangeRender();
23767
23816
  } else if (name == "align") {
23768
23817
  setAlign(editor.value, dataRangeCaches.value, val);
23769
23818
  editor.value.formatElementStack();
@@ -24186,6 +24235,22 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
24186
24235
  () => h(Icon, { value: "quote" })
24187
24236
  );
24188
24237
  }
24238
+ if (itemProps.name == "separator" && separatorConfig.value.show) {
24239
+ return h(
24240
+ Button,
24241
+ {
24242
+ ...itemProps,
24243
+ title: $editTrans("separator"),
24244
+ leftBorder: separatorConfig.value.leftBorder,
24245
+ rightBorder: separatorConfig.value.rightBorder,
24246
+ color: props.color,
24247
+ disabled: separatorConfig.value.disabled || selfProps.disabled || disabled.value,
24248
+ active: separatorConfig.value.active,
24249
+ onOperate: handleOperate
24250
+ },
24251
+ () => h(Icon, { value: "separator" })
24252
+ );
24253
+ }
24189
24254
  if (itemProps.name == "align" && alignConfig.value.show) {
24190
24255
  return h(
24191
24256
  Button,
@@ -24789,7 +24854,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
24789
24854
  };
24790
24855
  }
24791
24856
  });
24792
- const Menu = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-98c51b8e"]]);
24857
+ const Menu = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-13b11735"]]);
24793
24858
  const EditifyProps = {
24794
24859
  //国际化语言类型
24795
24860
  locale: {
@@ -24994,6 +25059,7 @@ const en_US = {
24994
25059
  undo: "Undo",
24995
25060
  redo: "Redo",
24996
25061
  quote: "Quote",
25062
+ separator: "Separator",
24997
25063
  lineHeight: "Line height",
24998
25064
  indent: "Indent",
24999
25065
  insertLink: "Insert Link",
@@ -25088,6 +25154,7 @@ const zh_CN = {
25088
25154
  undo: "撤销",
25089
25155
  redo: "重做",
25090
25156
  quote: "引用",
25157
+ separator: "分隔线",
25091
25158
  lineHeight: "行高",
25092
25159
  indent: "缩进",
25093
25160
  insertLink: "插入链接",
@@ -25330,7 +25397,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
25330
25397
  orderdListHandle(editor.value, el);
25331
25398
  },
25332
25399
  (el) => {
25333
- mediaHandle(editor.value, el);
25400
+ commonElementHandle(editor.value, el);
25334
25401
  },
25335
25402
  (el) => {
25336
25403
  tableHandle(editor.value, el);
@@ -25540,17 +25607,6 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
25540
25607
  }
25541
25608
  };
25542
25609
  const handleCustomParseNode = (ele) => {
25543
- if (ele.parsedom == "code") {
25544
- ele.parsedom = "span";
25545
- const marks = {
25546
- "data-editify-code": true
25547
- };
25548
- if (ele.hasMarks()) {
25549
- Object.assign(ele.marks, marks);
25550
- } else {
25551
- ele.marks = marks;
25552
- }
25553
- }
25554
25610
  pluginResultList.value.forEach((pluginResult) => {
25555
25611
  if (pluginResult.customParseNode) {
25556
25612
  ele = pluginResult.customParseNode(ele);
@@ -25885,7 +25941,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
25885
25941
  };
25886
25942
  }
25887
25943
  });
25888
- const Editify = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-4c71ae18"]]);
25944
+ const Editify = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-21167e28"]]);
25889
25945
  const InsertAttachmentProps = {
25890
25946
  //主题色
25891
25947
  color: {
@@ -26132,7 +26188,7 @@ const isAttachment = (element2) => {
26132
26188
  if (element2.isEmpty()) {
26133
26189
  return false;
26134
26190
  }
26135
- return element2.parsedom == "span" && element2.type == "closed" && element2.hasMarks() && element2.marks["data-attachment"];
26191
+ return element2.parsedom == "span" && element2.type == "closed" && element2.hasMarks() && element2.marks["data-editify-attachment"];
26136
26192
  };
26137
26193
  const hasAttachmentInRange = (editor, dataRangeCaches) => {
26138
26194
  if (!editor.range) {
@@ -26193,18 +26249,17 @@ const attachment = (options) => {
26193
26249
  const editor = editifyInstance.exposed.editor.value;
26194
26250
  urls.forEach((url) => {
26195
26251
  const marks = {
26196
- "data-attachment": url,
26197
- "data-attachment-name": name || editTrans("attachmentDefaultName"),
26198
- contenteditable: "false"
26252
+ "data-editify-attachment": url,
26253
+ "data-editify-attachment-name": name || editTrans("attachmentDefaultName")
26199
26254
  };
26200
26255
  const attachmentElement = new AlexElement("closed", "span", marks, null, null);
26201
26256
  editor.insertElement(attachmentElement);
26202
- const beforeText = AlexElement.getSpaceElement();
26203
- const afterText = AlexElement.getSpaceElement();
26204
- editor.addElementAfter(afterText, attachmentElement);
26205
- editor.addElementBefore(beforeText, attachmentElement);
26206
- editor.range.anchor.moveToStart(afterText);
26207
- editor.range.focus.moveToStart(afterText);
26257
+ const leftSpace = AlexElement.getSpaceElement();
26258
+ const rightSpace = AlexElement.getSpaceElement();
26259
+ editor.addElementBefore(leftSpace, attachmentElement);
26260
+ editor.addElementAfter(rightSpace, attachmentElement);
26261
+ editor.range.anchor.moveToEnd(rightSpace);
26262
+ editor.range.focus.moveToEnd(rightSpace);
26208
26263
  });
26209
26264
  editor.formatElementStack();
26210
26265
  editor.domRender();
@@ -26219,10 +26274,10 @@ const attachment = (options) => {
26219
26274
  updateView: () => {
26220
26275
  const editor = editifyInstance.exposed.editor.value;
26221
26276
  AlexElement.flatElements(editor.stack).forEach((el) => {
26222
- if (el.parsedom == "span" && el.hasMarks() && el.marks["data-attachment"]) {
26277
+ if (el.parsedom == "span" && el.hasMarks() && el.marks["data-editify-attachment"]) {
26223
26278
  event.off(el.elm, "click");
26224
26279
  event.on(el.elm, "click", async () => {
26225
- const url = el.marks["data-attachment"];
26280
+ const url = el.marks["data-editify-attachment"];
26226
26281
  const res = await fetch(url, {
26227
26282
  method: "GET"
26228
26283
  });
@@ -26230,28 +26285,31 @@ const attachment = (options) => {
26230
26285
  const a = document.createElement("a");
26231
26286
  a.setAttribute("target", "_blank");
26232
26287
  a.setAttribute("href", URL.createObjectURL(blob));
26233
- a.setAttribute("download", el.marks["data-attachment-name"]);
26288
+ a.setAttribute("download", el.marks["data-editify-attachment-name"]);
26234
26289
  a.click();
26235
26290
  });
26236
26291
  }
26237
26292
  });
26238
26293
  },
26239
- //span含有data-attachment的元素设为自闭合元素
26294
+ //span含有data-editify-attachment的元素设为自闭合元素
26240
26295
  customParseNode: (el) => {
26241
- if (el.hasMarks() && el.marks["data-attachment"] && el.parsedom == "span") {
26296
+ if (el.hasMarks() && el.marks["data-editify-attachment"] && el.parsedom == "span") {
26242
26297
  el.type = "closed";
26243
26298
  }
26244
26299
  return el;
26245
26300
  },
26246
- //span元素粘贴保留data-attachment
26301
+ //span元素粘贴保留data-editify-attachment
26247
26302
  pasteKeepMarks: {
26248
- "data-attachment": ["span"],
26249
- "data-attachment-name": ["span"]
26303
+ "data-editify-attachment": ["span"],
26304
+ "data-editify-attachment-name": ["span"]
26250
26305
  },
26251
26306
  //自定义渲染规范
26252
26307
  renderRule: (el) => {
26253
- if (el.type == "closed" && el.hasMarks() && el.marks["data-attachment"]) {
26308
+ if (el.hasMarks() && el.marks["data-editify-attachment"]) {
26254
26309
  el.marks["title"] = editTrans("attachmentDownloadTitle");
26310
+ if (!el.marks["data-editify-attachment-name"]) {
26311
+ el.marks["data-editify-attachment-name"] = editTrans("attachmentDefaultName");
26312
+ }
26255
26313
  const editor = editifyInstance.exposed.editor.value;
26256
26314
  const previousElement = editor.getPreviousElement(el);
26257
26315
  const newTextElement = editor.getNextElement(el);
@@ -26272,7 +26330,7 @@ const attachment = (options) => {
26272
26330
  const install = (app) => {
26273
26331
  app.component(Editify.name, Editify);
26274
26332
  };
26275
- const version = "0.1.36";
26333
+ const version = "0.1.37";
26276
26334
  console.log(`%c vue-editify %c v${version} `, "padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold;", "padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e; font-weight: bold;");
26277
26335
  export {
26278
26336
  AlexElement,