@truedat/core 8.3.4 → 8.3.5
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/Markdown.js +66 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/core",
|
|
3
|
-
"version": "8.3.
|
|
3
|
+
"version": "8.3.5",
|
|
4
4
|
"description": "Truedat Web Core",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@testing-library/jest-dom": "^6.6.3",
|
|
52
52
|
"@testing-library/react": "^16.3.0",
|
|
53
53
|
"@testing-library/user-event": "^14.6.1",
|
|
54
|
-
"@truedat/test": "8.3.
|
|
54
|
+
"@truedat/test": "8.3.5",
|
|
55
55
|
"identity-obj-proxy": "^3.0.0",
|
|
56
56
|
"jest": "^29.7.0",
|
|
57
57
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -96,5 +96,5 @@
|
|
|
96
96
|
"swr": "^2.3.3",
|
|
97
97
|
"turndown": "^7.2.2"
|
|
98
98
|
},
|
|
99
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "12d1969c3403861d360fbdc24fd270ab1fece070"
|
|
100
100
|
}
|
|
@@ -27,7 +27,7 @@ const extensions = [
|
|
|
27
27
|
rel: "noopener noreferrer",
|
|
28
28
|
target: "_blank",
|
|
29
29
|
},
|
|
30
|
-
}),
|
|
30
|
+
}),
|
|
31
31
|
];
|
|
32
32
|
|
|
33
33
|
const validateUrl = (value, allowEmpty = false) => {
|
|
@@ -38,39 +38,39 @@ const validateUrl = (value, allowEmpty = false) => {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
// URLs con espacios no son válidas
|
|
42
41
|
if (value.includes(" ")) {
|
|
43
42
|
return { valid: false, error: "markdown.editor.invalidUrl" };
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
// Regex más estricto: requiere dominio.tld válido
|
|
47
|
-
// - Dominio: al menos 2 caracteres antes del último punto
|
|
48
|
-
// - TLD: 2-6 letras
|
|
49
45
|
const parts = value.split(".");
|
|
50
46
|
if (parts.length < 2) {
|
|
51
47
|
return { valid: false, error: "markdown.editor.invalidUrl" };
|
|
52
48
|
}
|
|
53
|
-
|
|
49
|
+
|
|
54
50
|
const tld = parts[parts.length - 1].split("/")[0];
|
|
55
51
|
const domain = parts.slice(0, -1).join(".");
|
|
56
|
-
|
|
57
|
-
// Validar TLD: 2-6 letras
|
|
52
|
+
|
|
58
53
|
if (!/^[a-z]{2,6}$/i.test(tld)) {
|
|
59
54
|
return { valid: false, error: "markdown.editor.invalidUrl" };
|
|
60
55
|
}
|
|
61
|
-
|
|
62
|
-
// Validar dominio: al menos 4 caracteres si el TLD tiene 3 letras o menos
|
|
63
|
-
// Esto evita www.peo, www.xyz, etc. pero permite example.com
|
|
56
|
+
|
|
64
57
|
if (tld.length <= 3 && domain.length < 4) {
|
|
65
58
|
return { valid: false, error: "markdown.editor.invalidUrl" };
|
|
66
59
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
|
|
61
|
+
if (
|
|
62
|
+
domain.length < 2 ||
|
|
63
|
+
domain.startsWith("-") ||
|
|
64
|
+
domain.endsWith("-") ||
|
|
65
|
+
domain.endsWith(".")
|
|
66
|
+
) {
|
|
70
67
|
return { valid: false, error: "markdown.editor.invalidUrl" };
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
const urlWithProtocol = value.match(/^https?:\/\//i)
|
|
70
|
+
const urlWithProtocol = value.match(/^https?:\/\//i)
|
|
71
|
+
? value
|
|
72
|
+
: `https://${value}`;
|
|
73
|
+
|
|
74
74
|
return { valid: true, value: urlWithProtocol };
|
|
75
75
|
};
|
|
76
76
|
|
|
@@ -78,8 +78,16 @@ function markdownToHtml(markdown) {
|
|
|
78
78
|
if (!markdown || (typeof markdown === "string" && markdown.trim() === "")) {
|
|
79
79
|
return "<p></p>";
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
return marked
|
|
82
|
+
.parse(markdown, { async: false })
|
|
83
|
+
.replace(
|
|
84
|
+
/<a (?=[^>]*href=)/gi,
|
|
85
|
+
`<a target="_blank" rel="noopener noreferrer" `,
|
|
86
|
+
)
|
|
87
|
+
.replace(
|
|
88
|
+
/href="(?!https?:\/\/|mailto:)([^"]+)"/gi,
|
|
89
|
+
(match, url) => `href="https://${url}"`,
|
|
90
|
+
);
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
function htmlToMarkdown(html) {
|
|
@@ -195,44 +203,55 @@ export function MarkdownEditor({
|
|
|
195
203
|
};
|
|
196
204
|
}, [editor]);
|
|
197
205
|
|
|
198
|
-
const openLinkModal = useCallback(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (url !== null) {
|
|
202
|
-
linkUrl = url.replace(/^https?:\/\//i, "");
|
|
203
|
-
} else {
|
|
206
|
+
const openLinkModal = useCallback(
|
|
207
|
+
(url = null) => {
|
|
204
208
|
const previousUrl = editor.getAttributes("link").href || "";
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
const tempUrl = url !== null ? url : previousUrl;
|
|
210
|
+
const linkUrl = tempUrl.replace(/^https?:\/\//i, "");
|
|
207
211
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
212
|
+
setLinkUrl(linkUrl);
|
|
213
|
+
setLinkModalOpen(true);
|
|
214
|
+
},
|
|
215
|
+
[editor],
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const handleLinkAccept = useCallback(
|
|
219
|
+
({ valid, value: url }) => {
|
|
220
|
+
if (!valid) return;
|
|
211
221
|
|
|
212
|
-
|
|
213
|
-
|
|
222
|
+
if (!url || url.trim() === "") {
|
|
223
|
+
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
224
|
+
setLinkModalOpen(false);
|
|
225
|
+
setLinkUrl("");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const finalUrl = url.startsWith("http") ? url : `https://${url}`;
|
|
214
230
|
|
|
215
|
-
|
|
216
|
-
|
|
231
|
+
editor
|
|
232
|
+
.chain()
|
|
233
|
+
.focus()
|
|
234
|
+
.extendMarkRange("link")
|
|
235
|
+
.setLink({ href: finalUrl })
|
|
236
|
+
.run();
|
|
217
237
|
setLinkModalOpen(false);
|
|
218
238
|
setLinkUrl("");
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
|
|
223
|
-
setLinkModalOpen(false);
|
|
224
|
-
setLinkUrl("");
|
|
225
|
-
}, [editor]);
|
|
239
|
+
},
|
|
240
|
+
[editor],
|
|
241
|
+
);
|
|
226
242
|
|
|
227
243
|
const handleLinkCancel = useCallback(() => {
|
|
228
244
|
setLinkModalOpen(false);
|
|
229
245
|
setLinkUrl("");
|
|
230
246
|
}, []);
|
|
231
247
|
|
|
232
|
-
const validateLinkUrl = useCallback(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
248
|
+
const validateLinkUrl = useCallback(
|
|
249
|
+
(value) => {
|
|
250
|
+
const hasPreviousLink = editor?.isActive("link");
|
|
251
|
+
return validateUrl(value, hasPreviousLink);
|
|
252
|
+
},
|
|
253
|
+
[editor],
|
|
254
|
+
);
|
|
236
255
|
|
|
237
256
|
if (!editor) {
|
|
238
257
|
return null;
|
|
@@ -327,7 +346,10 @@ export function MarkdownEditor({
|
|
|
327
346
|
<FormattedMessage id="markdown.editor.insertLink" />
|
|
328
347
|
</>
|
|
329
348
|
}
|
|
330
|
-
label={formatMessage({
|
|
349
|
+
label={formatMessage({
|
|
350
|
+
id: "markdown.editor.urlLabel",
|
|
351
|
+
defaultMessage: "URL",
|
|
352
|
+
})}
|
|
331
353
|
placeholder="https://"
|
|
332
354
|
/>
|
|
333
355
|
</div>
|