vuewrite 0.0.18 → 0.0.20

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.
@@ -213,6 +213,11 @@ declare class TextEditorStore {
213
213
  removeNewLine(): void;
214
214
  onInput(_e: Event): void;
215
215
  addNewLine(): void;
216
+ addNewLineAfter(): {
217
+ id: string;
218
+ text: string;
219
+ styles: never[];
220
+ };
216
221
  insertText(data: string): void;
217
222
  insertBlock(blockData: Partial<Block>): void;
218
223
  get startAndEnd(): [{
package/dist/vuewrite.js CHANGED
@@ -366,6 +366,12 @@ class TextEditorStore {
366
366
  this.selection.focus = { blockId: block.id, offset: 0 };
367
367
  this.history.push("setText");
368
368
  }
369
+ addNewLineAfter() {
370
+ const index = this.blocks.findIndex((item) => item.id === this.selection.anchor.blockId);
371
+ const block = { id: uid(), text: "", styles: [] };
372
+ this.blocks.splice(index + 1, 0, block);
373
+ return block;
374
+ }
369
375
  insertText(data) {
370
376
  const block = this.currentBlock;
371
377
  if (!block)
@@ -388,7 +394,11 @@ class TextEditorStore {
388
394
  }
389
395
  Object.assign(this.currentBlock, blockData);
390
396
  if (blockData.editable === false && this.currentBlock === this.blocks[this.blocks.length - 1]) {
391
- this.addNewLine();
397
+ const newLine = this.addNewLineAfter();
398
+ this.selection.focus.blockId = newLine.id;
399
+ this.selection.focus.offset = 0;
400
+ this.selection.anchor.blockId = newLine.id;
401
+ this.selection.anchor.offset = 0;
392
402
  }
393
403
  this.history.push("setText");
394
404
  }
@@ -606,12 +616,16 @@ const _sfc_main$2 = defineComponent({
606
616
  const markers = [];
607
617
  if (block.styles) {
608
618
  for (let style of block.styles) {
619
+ if (style.end <= style.start)
620
+ continue;
609
621
  markers.push([style.start, style]);
610
622
  markers.push([style.end, style]);
611
623
  }
612
624
  }
613
625
  if (props.parser) {
614
626
  for (let style of props.parser(text)) {
627
+ if (style.end <= style.start)
628
+ continue;
615
629
  markers.push([style.start, style]);
616
630
  markers.push([style.end, style]);
617
631
  }
@@ -676,6 +690,112 @@ const _sfc_main$2 = defineComponent({
676
690
  };
677
691
  }
678
692
  });
693
+ const createClipboardEvents = (store, props) => {
694
+ const getSelected = () => {
695
+ const [start, end, startIndex, endIndex] = store.startAndEnd;
696
+ if (startIndex === endIndex) {
697
+ const text2 = store.blocks[startIndex].text.slice(start.offset, end.offset);
698
+ return [
699
+ new ClipboardItem({
700
+ "text/plain": new Blob([text2], { type: "text/plain" })
701
+ })
702
+ ];
703
+ }
704
+ const startText = store.blocks[startIndex].text.slice(start.offset);
705
+ const endText = store.blocks[endIndex].text.slice(0, end.offset);
706
+ const arr = [
707
+ { type: store.blocks[startIndex].type, text: startText },
708
+ ...store.blocks.slice(startIndex + 1, endIndex),
709
+ { type: store.blocks[endIndex].type, text: endText }
710
+ ];
711
+ const html = arr.map((item) => `<div>${item.text}</div>`).join("\n");
712
+ const text = arr.map((item) => item.text).join("\n");
713
+ return [
714
+ new ClipboardItem({
715
+ "text/html": new Blob([html], { type: "text/html" }),
716
+ "text/plain": new Blob([text], { type: "text/plain" })
717
+ })
718
+ ];
719
+ };
720
+ const onCopy = (e) => {
721
+ if (e.defaultPrevented)
722
+ return;
723
+ e.preventDefault();
724
+ navigator.clipboard.write(getSelected());
725
+ store.history.push("setText");
726
+ };
727
+ const onCut = (e) => {
728
+ if (e.defaultPrevented)
729
+ return;
730
+ e.preventDefault();
731
+ navigator.clipboard.write(getSelected());
732
+ store.deleteSelected();
733
+ store.history.push("setText");
734
+ };
735
+ const insertText = (text) => {
736
+ if (props.preventMultiline) {
737
+ const blocks = text.split("\n");
738
+ store.insertText(blocks[0]);
739
+ for (let i = 1; i < blocks.length; i++) {
740
+ store.addNewLine();
741
+ store.insertText(blocks[i]);
742
+ }
743
+ } else {
744
+ store.insertText(text);
745
+ }
746
+ };
747
+ const parseHtml = (node) => {
748
+ var _a;
749
+ let isTextNode = false;
750
+ for (let _node of node.childNodes) {
751
+ if (_node.nodeType === Node.TEXT_NODE && ((_a = _node.textContent) == null ? void 0 : _a.trim()) || _node.nodeType == Node.ELEMENT_NODE && _node.tagName === "SPAN") {
752
+ isTextNode = true;
753
+ break;
754
+ }
755
+ }
756
+ if (isTextNode) {
757
+ const text = node.textContent;
758
+ if (!text)
759
+ return;
760
+ insertText(text);
761
+ store.addNewLine();
762
+ return;
763
+ }
764
+ for (let child of node.children) {
765
+ if (child.tagName === "DIV") {
766
+ parseHtml(child);
767
+ } else {
768
+ insertText(child.textContent ?? "");
769
+ store.addNewLine();
770
+ }
771
+ }
772
+ };
773
+ const parser = new DOMParser();
774
+ const onPaste = (e) => {
775
+ var _a, _b;
776
+ if (e.defaultPrevented)
777
+ return;
778
+ e.preventDefault();
779
+ const html = (_a = e.clipboardData) == null ? void 0 : _a.getData("text/html");
780
+ if (html) {
781
+ store.deleteSelected();
782
+ const dom = parser.parseFromString(html, "text/html");
783
+ parseHtml(dom.body);
784
+ } else {
785
+ const text = (_b = e.clipboardData) == null ? void 0 : _b.getData("text");
786
+ if (!text)
787
+ return;
788
+ store.deleteSelected();
789
+ insertText(text);
790
+ }
791
+ store.history.push("setText");
792
+ };
793
+ return {
794
+ onCopy,
795
+ onCut,
796
+ onPaste
797
+ };
798
+ };
679
799
  const _sfc_main$1 = /* @__PURE__ */ defineComponent({
680
800
  __name: "TextEditor",
681
801
  props: {
@@ -842,26 +962,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
842
962
  }
843
963
  store.history.push("setText");
844
964
  });
845
- const onCopy = (e) => {
846
- e.preventDefault();
847
- navigator.clipboard.writeText(store.selectedText);
848
- store.history.push("setText");
849
- };
850
- const onCut = (e) => {
851
- e.preventDefault();
852
- navigator.clipboard.writeText(store.selectedText);
853
- store.deleteSelected();
854
- store.history.push("setText");
855
- };
856
- const onPaste = (e) => {
857
- var _a;
858
- e.preventDefault();
859
- const text = (_a = e.clipboardData) == null ? void 0 : _a.getData("Text");
860
- if (!text)
861
- return;
862
- store.insertText(text);
863
- store.history.push("setText");
864
- };
965
+ const { onCut, onCopy, onPaste } = createClipboardEvents(store, props);
865
966
  const getClientRects = (selection) => {
866
967
  const anchor = getNode(selection.anchor.blockId);
867
968
  const focus = getNode(selection.focus.blockId);
@@ -898,9 +999,12 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
898
999
  onBeforeinput: _cache[0] || (_cache[0] = //@ts-ignore
899
1000
  (...args) => unref(store).onInput && unref(store).onInput(...args)),
900
1001
  onKeydown: onKeyDown,
901
- onCopy,
902
- onPaste,
903
- onCut
1002
+ onCopy: _cache[1] || (_cache[1] = //@ts-ignore
1003
+ (...args) => unref(onCopy) && unref(onCopy)(...args)),
1004
+ onPaste: _cache[2] || (_cache[2] = //@ts-ignore
1005
+ (...args) => unref(onPaste) && unref(onPaste)(...args)),
1006
+ onCut: _cache[3] || (_cache[3] = //@ts-ignore
1007
+ (...args) => unref(onCut) && unref(onCut)(...args))
904
1008
  }, [
905
1009
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(store).blocks, (block) => {
906
1010
  return openBlock(), createBlock(_sfc_main$2, {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vuewrite",
3
3
  "description": "Rich Text Editor based on Vue3 reactivity",
4
4
  "private": false,
5
- "version": "0.0.18",
5
+ "version": "0.0.20",
6
6
  "type": "module",
7
7
  "license": "MIT",
8
8
  "author": "den59k",
@@ -19,7 +19,8 @@
19
19
  "preview": "vite preview"
20
20
  },
21
21
  "dependencies": {
22
- "vue": "^3"
22
+ "vue": "^3",
23
+ "vuewrite": "^0.0.19"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@vitejs/plugin-vue": "^5.0.4",