layers-design-system 2.0.10 → 2.1.0
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/package.json +3 -3
- package/src/components/LNotification/index.vue +1 -1
- package/src/components/LSearchBar/Filters/Editors/index.js +4 -4
- package/src/components/LSearchBar/Filters/Views/index.js +4 -4
- package/src/components/LSearchBar/index.vue +2 -2
- package/src/components/LTable/FieldTypes/index.js +5 -5
- package/src/components/LTable/LTableHeader.vue +2 -2
- package/src/components/LTable/LTableHeaderCell.vue +1 -1
- package/src/components/LTable/index.vue +7 -7
- package/src/components/LTextEditor/LinkBox.vue +6 -3
- package/src/components/LTextEditor/helpers/addProtocol.js +5 -0
- package/src/components/LTextEditor/index.vue +108 -110
- package/src/components/LTextEditor/helpers/manageLinks.js +0 -60
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "layers-design-system",
|
|
3
3
|
"main": "src/main.js",
|
|
4
|
-
"version": "2.0
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "vue-cli-service serve ./src/main-docs.js",
|
|
7
7
|
"build": "vue-cli-service build --target lib ./src/main.js",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@tiptap/extension-text": "2.0.0-beta.13",
|
|
27
27
|
"@tiptap/extension-underline": "2.0.0-beta.16",
|
|
28
28
|
"@tiptap/vue-2": "2.0.0-beta.60",
|
|
29
|
+
"autolinker": "^4.0.0",
|
|
29
30
|
"currency.js": "1.2.2",
|
|
30
31
|
"dayjs": "^1.11.7",
|
|
31
32
|
"dompurify": "2.3.3",
|
|
@@ -33,7 +34,6 @@
|
|
|
33
34
|
"layers-utils": "1.0.4",
|
|
34
35
|
"mustache": "4.2.0",
|
|
35
36
|
"tiptap": "1.32.2",
|
|
36
|
-
"url-regex-safe": "2.0.2",
|
|
37
37
|
"vant": "2.12.30",
|
|
38
38
|
"vue": "2.6.14",
|
|
39
39
|
"vue-router": "3.5.2",
|
|
@@ -41,7 +41,6 @@
|
|
|
41
41
|
"vuetify": "2.5.10"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"sass-loader": "7.3.1",
|
|
45
44
|
"@vue/cli-plugin-babel": "4.5.14",
|
|
46
45
|
"@vue/cli-plugin-eslint": "4.5.14",
|
|
47
46
|
"@vue/cli-service": "4.5.14",
|
|
@@ -50,6 +49,7 @@
|
|
|
50
49
|
"eslint-plugin-vue": "5.2.3",
|
|
51
50
|
"hard-source-webpack-plugin": "0.13.1",
|
|
52
51
|
"sass": "1.43.2",
|
|
52
|
+
"sass-loader": "7.3.1",
|
|
53
53
|
"vue-cli-plugin-element": "1.0.1",
|
|
54
54
|
"vue-cli-plugin-vuetify": "2.4.3",
|
|
55
55
|
"vue-template-compiler": "2.6.14",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import StringEditor from "./StringEditor";
|
|
2
|
-
import AmountEditor from "./AmountEditor";
|
|
3
|
-
import NumberEditor from "./NumberEditor";
|
|
4
|
-
import DateEditor from "./DateEditor";
|
|
1
|
+
import StringEditor from "./StringEditor.vue";
|
|
2
|
+
import AmountEditor from "./AmountEditor.vue";
|
|
3
|
+
import NumberEditor from "./NumberEditor.vue";
|
|
4
|
+
import DateEditor from "./DateEditor.vue";
|
|
5
5
|
|
|
6
6
|
import { FieldTypeComponents } from '../../../../helpers/FieldTypeComponents'
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import StringView from "./StringView";
|
|
2
|
-
import AmountView from "./AmountView";
|
|
3
|
-
import NumberView from "./NumberView";
|
|
4
|
-
import DateView from "./DateView";
|
|
1
|
+
import StringView from "./StringView.vue";
|
|
2
|
+
import AmountView from "./AmountView.vue";
|
|
3
|
+
import NumberView from "./NumberView.vue";
|
|
4
|
+
import DateView from "./DateView.vue";
|
|
5
5
|
|
|
6
6
|
import { FieldTypeComponents } from '../../../../helpers/FieldTypeComponents'
|
|
7
7
|
|
|
@@ -49,8 +49,8 @@ import isEqual from "lodash/isEqual";
|
|
|
49
49
|
import findIndex from "lodash/findIndex";
|
|
50
50
|
import find from "lodash/find";
|
|
51
51
|
|
|
52
|
-
import AddFilterButton from "./AddFilterButton";
|
|
53
|
-
import FilterChip from "./Filters/FilterChip";
|
|
52
|
+
import AddFilterButton from "./AddFilterButton.vue";
|
|
53
|
+
import FilterChip from "./Filters/FilterChip.vue";
|
|
54
54
|
|
|
55
55
|
export default {
|
|
56
56
|
tagName: "l-search-bar",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import StringView from "./StringView";
|
|
2
|
-
import NumberView from "./NumberView";
|
|
3
|
-
import AmountView from "./AmountView";
|
|
4
|
-
import EmailView from "./EmailView";
|
|
5
|
-
import DateView from "./DateView";
|
|
1
|
+
import StringView from "./StringView.vue";
|
|
2
|
+
import NumberView from "./NumberView.vue";
|
|
3
|
+
import AmountView from "./AmountView.vue";
|
|
4
|
+
import EmailView from "./EmailView.vue";
|
|
5
|
+
import DateView from "./DateView.vue";
|
|
6
6
|
|
|
7
7
|
import { FieldTypeComponents } from '../../../helpers/FieldTypeComponents'
|
|
8
8
|
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
</template>
|
|
32
32
|
|
|
33
33
|
<script>
|
|
34
|
-
import LTableHeaderCell from "./LTableHeaderCell";
|
|
35
|
-
import LTableHeaderLoader from "./LTableHeaderLoader";
|
|
34
|
+
import LTableHeaderCell from "./LTableHeaderCell.vue";
|
|
35
|
+
import LTableHeaderLoader from "./LTableHeaderLoader.vue";
|
|
36
36
|
|
|
37
37
|
export default {
|
|
38
38
|
components: { LTableHeaderCell, LTableHeaderLoader },
|
|
@@ -78,13 +78,13 @@
|
|
|
78
78
|
import FieldTypes from "./FieldTypes";
|
|
79
79
|
FieldTypes.register();
|
|
80
80
|
|
|
81
|
-
import LTableBody from "./LTableBody";
|
|
82
|
-
import LTableHeader from "./LTableHeader";
|
|
83
|
-
import LTableEndspace from "./LTableEndspace"
|
|
84
|
-
import LTableLoadMore from "./LTableLoadMore";
|
|
85
|
-
import LTableReloader from "./LTableReloader";
|
|
86
|
-
import LTableBodySpacer from "./LTableBodySpacer";
|
|
87
|
-
import LTablePagination from "./LTablePagination";
|
|
81
|
+
import LTableBody from "./LTableBody.vue";
|
|
82
|
+
import LTableHeader from "./LTableHeader.vue";
|
|
83
|
+
import LTableEndspace from "./LTableEndspace.vue"
|
|
84
|
+
import LTableLoadMore from "./LTableLoadMore.vue";
|
|
85
|
+
import LTableReloader from "./LTableReloader.vue";
|
|
86
|
+
import LTableBodySpacer from "./LTableBodySpacer.vue";
|
|
87
|
+
import LTablePagination from "./LTablePagination.vue";
|
|
88
88
|
|
|
89
89
|
import {changeSelection} from './helpers'
|
|
90
90
|
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
</template>
|
|
28
28
|
|
|
29
29
|
<script>
|
|
30
|
-
import
|
|
31
|
-
import { addProtocol } from './helpers/
|
|
30
|
+
import Autolinker from 'autolinker'
|
|
31
|
+
import { addProtocol } from './helpers/addProtocol'
|
|
32
32
|
|
|
33
33
|
export default {
|
|
34
34
|
props: {
|
|
@@ -57,7 +57,10 @@ export default {
|
|
|
57
57
|
},
|
|
58
58
|
|
|
59
59
|
isLinkValid(link) {
|
|
60
|
-
|
|
60
|
+
const validating = Autolinker.link(link, {
|
|
61
|
+
email: false,
|
|
62
|
+
})
|
|
63
|
+
return validating.includes('href')
|
|
61
64
|
},
|
|
62
65
|
},
|
|
63
66
|
|
|
@@ -63,36 +63,36 @@
|
|
|
63
63
|
</template>
|
|
64
64
|
|
|
65
65
|
<script>
|
|
66
|
-
import { Editor, EditorContent, BubbleMenu } from
|
|
67
|
-
import Document from
|
|
68
|
-
import Text from
|
|
69
|
-
import ListItem from
|
|
66
|
+
import { Editor, EditorContent, BubbleMenu } from "@tiptap/vue-2";
|
|
67
|
+
import Document from "@tiptap/extension-document";
|
|
68
|
+
import Text from "@tiptap/extension-text";
|
|
69
|
+
import ListItem from "@tiptap/extension-list-item";
|
|
70
70
|
|
|
71
71
|
//Layers Custom Extensions
|
|
72
|
-
import LayersParagraph from
|
|
73
|
-
import LayersBold from
|
|
74
|
-
import LayersItalic from
|
|
75
|
-
import LayersUnderline from
|
|
76
|
-
import LayersHeading from
|
|
77
|
-
import LayersBulletList from
|
|
78
|
-
import LayersOrderedList from
|
|
79
|
-
import LayersBlockquote from
|
|
80
|
-
import LayersLink from
|
|
81
|
-
import LayersPlaceholder from
|
|
82
|
-
import LayersBreakLine from
|
|
83
|
-
import LayersHistory from
|
|
72
|
+
import LayersParagraph from "./extensions/LayersParagraph";
|
|
73
|
+
import LayersBold from "./extensions/LayersBold";
|
|
74
|
+
import LayersItalic from "./extensions/LayersItalic";
|
|
75
|
+
import LayersUnderline from "./extensions/LayersUnderline";
|
|
76
|
+
import LayersHeading from "./extensions/LayersHeading";
|
|
77
|
+
import LayersBulletList from "./extensions/LayersBulletList";
|
|
78
|
+
import LayersOrderedList from "./extensions/LayersOrderedList";
|
|
79
|
+
import LayersBlockquote from "./extensions/LayersBlockquote";
|
|
80
|
+
import LayersLink from "./extensions/LayersLink";
|
|
81
|
+
import LayersPlaceholder from "./extensions/LayersPlaceholder";
|
|
82
|
+
import LayersBreakLine from "./extensions/LayersBreakLine";
|
|
83
|
+
import LayersHistory from "./extensions/LayersHistory";
|
|
84
84
|
|
|
85
85
|
//Custom Components
|
|
86
|
-
import LinkBox from
|
|
87
|
-
import FloatingLink from
|
|
86
|
+
import LinkBox from "./LinkBox.vue";
|
|
87
|
+
import FloatingLink from "./FloatingLink.vue";
|
|
88
88
|
|
|
89
89
|
//Helpers
|
|
90
|
-
import
|
|
91
|
-
import
|
|
92
|
-
import
|
|
90
|
+
import removeEmptyTags from "./helpers/removeEmptyTags.js";
|
|
91
|
+
import DOMPurify from "dompurify";
|
|
92
|
+
import Autolinker from "autolinker";
|
|
93
93
|
|
|
94
94
|
export default {
|
|
95
|
-
tagName:
|
|
95
|
+
tagName: "l-text-editor",
|
|
96
96
|
|
|
97
97
|
props: {
|
|
98
98
|
value: String,
|
|
@@ -110,77 +110,77 @@ export default {
|
|
|
110
110
|
editor: null,
|
|
111
111
|
markUps: [
|
|
112
112
|
{
|
|
113
|
-
name:
|
|
114
|
-
tooltip:
|
|
115
|
-
icon:
|
|
113
|
+
name: "bold",
|
|
114
|
+
tooltip: "Negrito",
|
|
115
|
+
icon: "uil-bold",
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
|
-
name:
|
|
119
|
-
tooltip:
|
|
120
|
-
icon:
|
|
118
|
+
name: "italic",
|
|
119
|
+
tooltip: "Itálico",
|
|
120
|
+
icon: "uil-italic",
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
|
-
name:
|
|
124
|
-
tooltip:
|
|
125
|
-
icon:
|
|
123
|
+
name: "underline",
|
|
124
|
+
tooltip: "Sublinhado",
|
|
125
|
+
icon: "uil-underline",
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
|
-
name:
|
|
129
|
-
tooltip:
|
|
130
|
-
icon: require(
|
|
128
|
+
name: "heading",
|
|
129
|
+
tooltip: "Título",
|
|
130
|
+
icon: require("../../assets/button-text-editor/title.svg"),
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
|
-
name:
|
|
134
|
-
tooltip:
|
|
135
|
-
icon:
|
|
133
|
+
name: "bulletList",
|
|
134
|
+
tooltip: "Lista com marcadores",
|
|
135
|
+
icon: "uil-list-ul",
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
|
-
name:
|
|
139
|
-
tooltip:
|
|
140
|
-
icon:
|
|
138
|
+
name: "orderedList",
|
|
139
|
+
tooltip: "Lista numerada",
|
|
140
|
+
icon: "uil-list-ol-alt",
|
|
141
141
|
},
|
|
142
142
|
{
|
|
143
|
-
name:
|
|
144
|
-
tooltip:
|
|
145
|
-
icon:
|
|
143
|
+
name: "link",
|
|
144
|
+
tooltip: "Inserir link",
|
|
145
|
+
icon: "uil-link-alt",
|
|
146
146
|
},
|
|
147
147
|
{
|
|
148
|
-
name:
|
|
149
|
-
tooltip:
|
|
150
|
-
icon: require(
|
|
148
|
+
name: "blockquote",
|
|
149
|
+
tooltip: "Citação",
|
|
150
|
+
icon: require("../../assets/button-text-editor/double-quotes.svg"),
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
|
-
name:
|
|
154
|
-
tooltip:
|
|
155
|
-
icon: require(
|
|
153
|
+
name: "removeFormatting",
|
|
154
|
+
tooltip: "Remover formatação",
|
|
155
|
+
icon: require("../../assets/button-text-editor/remove-formatting.svg"),
|
|
156
156
|
},
|
|
157
157
|
],
|
|
158
158
|
showLinkBox: false,
|
|
159
159
|
isEditorFocused: null,
|
|
160
160
|
tooltipDelay: 125,
|
|
161
|
-
}
|
|
161
|
+
};
|
|
162
162
|
},
|
|
163
163
|
|
|
164
164
|
methods: {
|
|
165
165
|
isUnicon(value) {
|
|
166
|
-
return value.startsWith(
|
|
166
|
+
return value.startsWith("uil-");
|
|
167
167
|
},
|
|
168
168
|
|
|
169
169
|
markUpText(type) {
|
|
170
|
-
if (type ===
|
|
171
|
-
this.toggleLinkBox()
|
|
172
|
-
return
|
|
170
|
+
if (type === "link") {
|
|
171
|
+
this.toggleLinkBox();
|
|
172
|
+
return;
|
|
173
173
|
}
|
|
174
|
-
const commandChain = this.editor.chain().focus()
|
|
175
|
-
commandChain.setMarkUp(type).run()
|
|
174
|
+
const commandChain = this.editor.chain().focus();
|
|
175
|
+
commandChain.setMarkUp(type).run();
|
|
176
176
|
},
|
|
177
177
|
|
|
178
178
|
toggleLinkBox() {
|
|
179
|
-
this.showLinkBox = !this.showLinkBox
|
|
179
|
+
this.showLinkBox = !this.showLinkBox;
|
|
180
180
|
},
|
|
181
181
|
closeLinkBox() {
|
|
182
|
-
this.editor.commands.focus()
|
|
183
|
-
this.toggleLinkBox()
|
|
182
|
+
this.editor.commands.focus();
|
|
183
|
+
this.toggleLinkBox();
|
|
184
184
|
},
|
|
185
185
|
|
|
186
186
|
markUpLink(info) {
|
|
@@ -188,91 +188,89 @@ export default {
|
|
|
188
188
|
this.editor
|
|
189
189
|
.chain()
|
|
190
190
|
.focus()
|
|
191
|
-
.extendMarkRange(
|
|
192
|
-
.setLink({ href: info.url, target:
|
|
193
|
-
.run()
|
|
191
|
+
.extendMarkRange("link")
|
|
192
|
+
.setLink({ href: info.url, target: "_blank" })
|
|
193
|
+
.run();
|
|
194
194
|
} else {
|
|
195
|
-
this.editor.commands.insertContent(
|
|
195
|
+
this.editor.commands.insertContent(Autolinker.link(info.insertedText));
|
|
196
196
|
}
|
|
197
197
|
},
|
|
198
198
|
markOffLink() {
|
|
199
|
-
this.editor
|
|
200
|
-
.chain()
|
|
201
|
-
.focus()
|
|
202
|
-
.extendMarkRange('link')
|
|
203
|
-
.unsetLink()
|
|
204
|
-
.run()
|
|
199
|
+
this.editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
205
200
|
},
|
|
206
201
|
|
|
207
202
|
hasSomeMarkUpActive() {
|
|
208
|
-
const textEditorContent = this.editor.getJSON().content
|
|
209
|
-
const textEditorMarkUps = this.markUps.map((markUp) => markUp.name)
|
|
203
|
+
const textEditorContent = this.editor.getJSON().content;
|
|
204
|
+
const textEditorMarkUps = this.markUps.map((markUp) => markUp.name);
|
|
210
205
|
|
|
211
|
-
const textNodesActive = textEditorContent.map((node) => node.type)
|
|
206
|
+
const textNodesActive = textEditorContent.map((node) => node.type);
|
|
212
207
|
|
|
213
208
|
const hasSomeNode = textNodesActive.some((node) =>
|
|
214
209
|
textEditorMarkUps.includes(node)
|
|
215
|
-
)
|
|
210
|
+
);
|
|
216
211
|
const hasSomeMark = textEditorContent.some((node) => {
|
|
217
|
-
if (node.hasOwnProperty(
|
|
218
|
-
return node.content.some((content) =>
|
|
212
|
+
if (node.hasOwnProperty("content")) {
|
|
213
|
+
return node.content.some((content) =>
|
|
214
|
+
content.hasOwnProperty("marks")
|
|
215
|
+
);
|
|
219
216
|
}
|
|
220
|
-
})
|
|
217
|
+
});
|
|
221
218
|
|
|
222
|
-
return hasSomeNode || hasSomeMark
|
|
219
|
+
return hasSomeNode || hasSomeMark;
|
|
223
220
|
},
|
|
224
221
|
|
|
225
222
|
addSpaceToFinalParagraphTag(text) {
|
|
226
|
-
return text.replace(/<\/p>/g,
|
|
223
|
+
return text.replace(/<\/p>/g, " </p>");
|
|
227
224
|
},
|
|
228
225
|
},
|
|
229
226
|
|
|
230
227
|
computed: {
|
|
231
228
|
previousURL() {
|
|
232
|
-
return this.editor.getAttributes(
|
|
229
|
+
return this.editor.getAttributes("link").href;
|
|
233
230
|
},
|
|
234
231
|
showFloatingLink() {
|
|
235
|
-
return this.editor.isActive(
|
|
232
|
+
return this.editor.isActive("link");
|
|
236
233
|
},
|
|
237
234
|
finalText() {
|
|
238
|
-
const textEditorHTML = this.editor.getHTML()
|
|
239
|
-
const textEditorHTMLSpaced =
|
|
240
|
-
|
|
235
|
+
const textEditorHTML = this.editor.getHTML();
|
|
236
|
+
const textEditorHTMLSpaced =
|
|
237
|
+
this.addSpaceToFinalParagraphTag(textEditorHTML);
|
|
238
|
+
const textEditorHTMLWithLinks = Autolinker.link(textEditorHTMLSpaced);
|
|
241
239
|
|
|
242
240
|
return DOMPurify.sanitize(removeEmptyTags(textEditorHTMLWithLinks), {
|
|
243
|
-
ADD_ATTR: [
|
|
244
|
-
})
|
|
241
|
+
ADD_ATTR: ["target"],
|
|
242
|
+
});
|
|
245
243
|
},
|
|
246
244
|
currentTextSelection() {
|
|
247
|
-
const { view, state } = this.editor
|
|
248
|
-
const { from, to } = view.state.selection
|
|
249
|
-
return state.doc.textBetween(from, to,
|
|
245
|
+
const { view, state } = this.editor;
|
|
246
|
+
const { from, to } = view.state.selection;
|
|
247
|
+
return state.doc.textBetween(from, to, "");
|
|
250
248
|
},
|
|
251
249
|
arrowXPosition() {
|
|
252
|
-
const arrowWidth = 16.8 //px
|
|
253
|
-
const buttonLink = this.$refs.link[0].$el
|
|
250
|
+
const arrowWidth = 16.8; //px
|
|
251
|
+
const buttonLink = this.$refs.link[0].$el;
|
|
254
252
|
|
|
255
253
|
//formula to position the arrow based on the button link position
|
|
256
254
|
const arrowLeftOffset =
|
|
257
|
-
buttonLink.offsetLeft + (buttonLink.offsetWidth - arrowWidth) / 2
|
|
258
|
-
return { left: `${arrowLeftOffset}px` }
|
|
255
|
+
buttonLink.offsetLeft + (buttonLink.offsetWidth - arrowWidth) / 2;
|
|
256
|
+
return { left: `${arrowLeftOffset}px` };
|
|
259
257
|
},
|
|
260
258
|
linkBoxPosition() {
|
|
261
|
-
const linkBoxWidth = 456 //px
|
|
262
|
-
const textEditorWidth = this.$refs.texteditor.$el.offsetWidth
|
|
263
|
-
const buttonLink = this.$refs.link[0].$el
|
|
264
|
-
let linkBoxLeftOffset
|
|
265
|
-
const overflowLimit = 500
|
|
259
|
+
const linkBoxWidth = 456; //px
|
|
260
|
+
const textEditorWidth = this.$refs.texteditor.$el.offsetWidth;
|
|
261
|
+
const buttonLink = this.$refs.link[0].$el;
|
|
262
|
+
let linkBoxLeftOffset;
|
|
263
|
+
const overflowLimit = 500;
|
|
266
264
|
|
|
267
265
|
if (textEditorWidth > overflowLimit) {
|
|
268
266
|
//formula to position the link box based on the screen width
|
|
269
|
-
linkBoxLeftOffset = `${
|
|
270
|
-
buttonLink.offsetWidth / 2 -
|
|
271
|
-
|
|
267
|
+
linkBoxLeftOffset = `${
|
|
268
|
+
buttonLink.offsetLeft + buttonLink.offsetWidth / 2 - linkBoxWidth / 2
|
|
269
|
+
}px`;
|
|
272
270
|
} else {
|
|
273
|
-
linkBoxLeftOffset =
|
|
271
|
+
linkBoxLeftOffset = "1rem";
|
|
274
272
|
}
|
|
275
|
-
return { left: linkBoxLeftOffset }
|
|
273
|
+
return { left: linkBoxLeftOffset };
|
|
276
274
|
},
|
|
277
275
|
},
|
|
278
276
|
|
|
@@ -298,23 +296,23 @@ export default {
|
|
|
298
296
|
content: this.value,
|
|
299
297
|
autofocus: false,
|
|
300
298
|
onUpdate: () => {
|
|
301
|
-
this.$emit(
|
|
302
|
-
this.$emit(
|
|
299
|
+
this.$emit("input", this.finalText);
|
|
300
|
+
this.$emit("useMarkUp", this.hasSomeMarkUpActive());
|
|
303
301
|
},
|
|
304
302
|
onFocus: () => {
|
|
305
|
-
this.isEditorFocused = true
|
|
306
|
-
this.$emit(
|
|
303
|
+
this.isEditorFocused = true;
|
|
304
|
+
this.$emit("focus", true);
|
|
307
305
|
},
|
|
308
306
|
onBlur: () => {
|
|
309
|
-
this.isEditorFocused = false
|
|
307
|
+
this.isEditorFocused = false;
|
|
310
308
|
},
|
|
311
|
-
})
|
|
309
|
+
});
|
|
312
310
|
},
|
|
313
311
|
|
|
314
312
|
beforeDestroy() {
|
|
315
|
-
this.editor.destroy()
|
|
313
|
+
this.editor.destroy();
|
|
316
314
|
},
|
|
317
|
-
}
|
|
315
|
+
};
|
|
318
316
|
</script>
|
|
319
317
|
|
|
320
318
|
<style scoped>
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
const urlRegex = require('url-regex-safe')
|
|
2
|
-
|
|
3
|
-
const customUrlRegex = new RegExp(
|
|
4
|
-
'((href=")?)' +
|
|
5
|
-
urlRegex({
|
|
6
|
-
localhost: false,
|
|
7
|
-
apostrophes: false,
|
|
8
|
-
returnString: true,
|
|
9
|
-
}) +
|
|
10
|
-
' ((</a>)?)',
|
|
11
|
-
'g'
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
function mountTagA(url) {
|
|
15
|
-
const href = addProtocol(url)
|
|
16
|
-
return getTagA(removeAnchorTag(href), url)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function getTagA(href, insertedText) {
|
|
20
|
-
return `<a target="_blank" rel="noopener noreferrer nofollow" class="color-link"
|
|
21
|
-
style="text-decoration: underline" href="${href}">${insertedText}</a>`
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function removeAnchorTag(string) {
|
|
25
|
-
return string.replace("</a>", "")
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function addProtocol(link) {
|
|
29
|
-
return link.startsWith('http://') || link.startsWith('https://')
|
|
30
|
-
? link
|
|
31
|
-
: 'https://' + link
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function mountLink(text) {
|
|
35
|
-
// Regular expression to match email addresses
|
|
36
|
-
const emailRegex = /(\b[\w.%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b)/g;
|
|
37
|
-
|
|
38
|
-
// Replace each email address in text with a mailto link
|
|
39
|
-
let finalText = text.replace(emailRegex, (email) => {
|
|
40
|
-
const href = `mailto:${email}`;
|
|
41
|
-
return getTagA(href, email);
|
|
42
|
-
});
|
|
43
|
-
let match;
|
|
44
|
-
|
|
45
|
-
// Loop through the text to find and replace URLs
|
|
46
|
-
while ((match = customUrlRegex.exec(finalText)) !== null) {
|
|
47
|
-
const url = match[0];
|
|
48
|
-
|
|
49
|
-
// Skip URLs that are parto of email addresses or already within anchor tags
|
|
50
|
-
if (finalText[match.index - 1] === '@' || url.startsWith('href="') || url.endsWith('</a>')) {
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
const finalIndex = match.index + url.length;
|
|
54
|
-
const finalUrl = mountTagA(url);
|
|
55
|
-
|
|
56
|
-
// Replace the URL with the formatted ancho tag
|
|
57
|
-
finalText = finalText.substring(0, match.index) + finalUrl + finalText.substring(finalIndex);
|
|
58
|
-
}
|
|
59
|
-
return finalText;
|
|
60
|
-
}
|