jodit 4.10.2 → 4.11.2
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/CHANGELOG.md +28 -0
- package/es2015/jodit.css +1 -1
- package/es2015/jodit.fat.min.js +121 -121
- package/es2015/jodit.js +36183 -35886
- package/es2015/jodit.min.js +121 -121
- package/es2015/plugins/debug/debug.css +1 -1
- package/es2015/plugins/debug/debug.js +1 -1
- package/es2015/plugins/debug/debug.min.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.js +724 -724
- package/es2015/plugins/speech-recognize/speech-recognize.min.js +2 -2
- package/es2018/jodit.fat.min.js +121 -121
- package/es2018/jodit.min.js +121 -121
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +2 -2
- package/es2021/jodit.css +1 -1
- package/es2021/jodit.fat.min.js +135 -135
- package/es2021/jodit.js +35482 -35186
- package/es2021/jodit.min.js +135 -135
- package/es2021/plugins/debug/debug.css +1 -1
- package/es2021/plugins/debug/debug.js +1 -1
- package/es2021/plugins/debug/debug.min.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.js +681 -681
- package/es2021/plugins/speech-recognize/speech-recognize.min.js +2 -2
- package/es2021.en/jodit.css +1 -1
- package/es2021.en/jodit.fat.min.js +151 -151
- package/es2021.en/jodit.js +34392 -34096
- package/es2021.en/jodit.min.js +135 -135
- package/es2021.en/plugins/debug/debug.css +1 -1
- package/es2021.en/plugins/debug/debug.js +1 -1
- package/es2021.en/plugins/debug/debug.min.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.js +306 -306
- package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +2 -2
- package/es5/jodit.css +2 -2
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +44054 -43700
- package/es5/jodit.min.css +2 -2
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/debug/debug.css +1 -1
- package/es5/plugins/debug/debug.js +1 -1
- package/es5/plugins/debug/debug.min.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.js +839 -839
- package/es5/plugins/speech-recognize/speech-recognize.min.js +2 -2
- package/es5/polyfills.fat.min.js +2 -2
- package/es5/polyfills.js +4211 -4211
- package/es5/polyfills.min.js +2 -2
- package/esm/config.d.ts +85 -0
- package/esm/core/constants.js +1 -1
- package/esm/core/dom/dom.d.ts +1 -0
- package/esm/core/helpers/html/safe-html.d.ts +3 -2
- package/esm/core/helpers/html/safe-html.js +42 -3
- package/esm/plugins/clean-html/clean-html.js +4 -0
- package/esm/plugins/clean-html/config.d.ts +85 -0
- package/esm/plugins/clean-html/config.js +7 -1
- package/esm/plugins/clean-html/helpers/visitor/filters/convert-unsafe-embeds.d.ts +14 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/convert-unsafe-embeds.js +37 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/index.d.ts +4 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/index.js +4 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/safe-links-target.d.ts +14 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/safe-links-target.js +38 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/sandbox-iframes-in-content.d.ts +14 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/sandbox-iframes-in-content.js +24 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/sanitize-attributes.js +10 -5
- package/esm/plugins/clean-html/helpers/visitor/filters/sanitize-styles.d.ts +14 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/sanitize-styles.js +70 -0
- package/esm/plugins/drag-and-drop/drag-and-drop.js +1 -1
- package/esm/plugins/enter/helpers/insert-paragraph.js +2 -1
- package/esm/plugins/file/file.js +3 -2
- package/esm/plugins/iframe/iframe.js +8 -6
- package/esm/plugins/image/image.js +3 -2
- package/esm/plugins/image-properties/writers/link.js +6 -0
- package/esm/plugins/link/link.js +15 -3
- package/esm/plugins/resizer/resizer.js +2 -2
- package/esm/plugins/source/editor/engines/area.js +3 -7
- package/package.json +1 -1
- package/types/config.d.ts +85 -0
- package/types/core/dom/dom.d.ts +1 -0
- package/types/core/helpers/html/safe-html.d.ts +3 -2
- package/types/plugins/clean-html/config.d.ts +85 -0
- package/types/plugins/clean-html/helpers/visitor/filters/convert-unsafe-embeds.d.ts +14 -0
- package/types/plugins/clean-html/helpers/visitor/filters/index.d.ts +4 -0
- package/types/plugins/clean-html/helpers/visitor/filters/safe-links-target.d.ts +14 -0
- package/types/plugins/clean-html/helpers/visitor/filters/sandbox-iframes-in-content.d.ts +14 -0
- package/types/plugins/clean-html/helpers/visitor/filters/sanitize-styles.d.ts +14 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { Dom } from "../../../../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../../../../core/helpers/utils/attr.js";
|
|
8
|
+
/**
|
|
9
|
+
* Convert `<object>` and `<embed>` elements to safer `<iframe>` elements.
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export function convertUnsafeEmbeds(jodit, nodeElm, hadEffect) {
|
|
13
|
+
const opt = jodit.o.cleanHTML.convertUnsafeEmbeds;
|
|
14
|
+
if (!opt || !Dom.isElement(nodeElm)) {
|
|
15
|
+
return hadEffect;
|
|
16
|
+
}
|
|
17
|
+
const tag = nodeElm.nodeName.toLowerCase();
|
|
18
|
+
if (!opt.includes(tag)) {
|
|
19
|
+
return hadEffect;
|
|
20
|
+
}
|
|
21
|
+
const elm = nodeElm;
|
|
22
|
+
const src = attr(elm, 'data') || attr(elm, 'src') || attr(elm, 'movie') || '';
|
|
23
|
+
if (!src) {
|
|
24
|
+
Dom.safeRemove(elm);
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const iframe = jodit.createInside.element('iframe');
|
|
28
|
+
attr(iframe, {
|
|
29
|
+
src,
|
|
30
|
+
sandbox: '',
|
|
31
|
+
frameborder: '0',
|
|
32
|
+
width: attr(elm, 'width'),
|
|
33
|
+
height: attr(elm, 'height')
|
|
34
|
+
});
|
|
35
|
+
Dom.replace(elm, iframe, undefined, false, true);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
@@ -10,9 +10,13 @@
|
|
|
10
10
|
* @private
|
|
11
11
|
*/
|
|
12
12
|
export * from "./allow-attributes";
|
|
13
|
+
export * from "./convert-unsafe-embeds";
|
|
13
14
|
export * from "./fill-empty-paragraph";
|
|
14
15
|
export * from "./remove-empty-text-node";
|
|
15
16
|
export * from "./remove-inv-text-nodes";
|
|
16
17
|
export * from "./replace-old-tags";
|
|
18
|
+
export * from "./safe-links-target";
|
|
19
|
+
export * from "./sandbox-iframes-in-content";
|
|
17
20
|
export * from "./sanitize-attributes";
|
|
21
|
+
export * from "./sanitize-styles";
|
|
18
22
|
export * from "./try-remove-node";
|
|
@@ -10,9 +10,13 @@
|
|
|
10
10
|
* @private
|
|
11
11
|
*/
|
|
12
12
|
export * from "./allow-attributes.js";
|
|
13
|
+
export * from "./convert-unsafe-embeds.js";
|
|
13
14
|
export * from "./fill-empty-paragraph.js";
|
|
14
15
|
export * from "./remove-empty-text-node.js";
|
|
15
16
|
export * from "./remove-inv-text-nodes.js";
|
|
16
17
|
export * from "./replace-old-tags.js";
|
|
18
|
+
export * from "./safe-links-target.js";
|
|
19
|
+
export * from "./sandbox-iframes-in-content.js";
|
|
17
20
|
export * from "./sanitize-attributes.js";
|
|
21
|
+
export * from "./sanitize-styles.js";
|
|
18
22
|
export * from "./try-remove-node.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/clean-html
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../../../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* Automatically add `rel="noopener noreferrer"` to links with `target="_blank"`
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
export declare function safeLinksTarget(jodit: IJodit, nodeElm: Node, hadEffect: boolean): boolean;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { Dom } from "../../../../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../../../../core/helpers/utils/attr.js";
|
|
8
|
+
/**
|
|
9
|
+
* Automatically add `rel="noopener noreferrer"` to links with `target="_blank"`
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export function safeLinksTarget(jodit, nodeElm, hadEffect) {
|
|
13
|
+
if (!jodit.o.cleanHTML.safeLinksTarget ||
|
|
14
|
+
!Dom.isElement(nodeElm) ||
|
|
15
|
+
nodeElm.nodeName !== 'A') {
|
|
16
|
+
return hadEffect;
|
|
17
|
+
}
|
|
18
|
+
const elm = nodeElm;
|
|
19
|
+
if (attr(elm, 'target') !== '_blank') {
|
|
20
|
+
return hadEffect;
|
|
21
|
+
}
|
|
22
|
+
const rel = attr(elm, 'rel') || '';
|
|
23
|
+
const parts = rel.split(/\s+/).filter(Boolean);
|
|
24
|
+
let changed = false;
|
|
25
|
+
if (!parts.includes('noopener')) {
|
|
26
|
+
parts.push('noopener');
|
|
27
|
+
changed = true;
|
|
28
|
+
}
|
|
29
|
+
if (!parts.includes('noreferrer')) {
|
|
30
|
+
parts.push('noreferrer');
|
|
31
|
+
changed = true;
|
|
32
|
+
}
|
|
33
|
+
if (changed) {
|
|
34
|
+
attr(elm, 'rel', parts.join(' '));
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return hadEffect;
|
|
38
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/clean-html
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../../../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* Add `sandbox=""` attribute to all `<iframe>` elements in the editor content
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
export declare function sandboxIframesInContent(jodit: IJodit, nodeElm: Node, hadEffect: boolean): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { Dom } from "../../../../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../../../../core/helpers/utils/attr.js";
|
|
8
|
+
/**
|
|
9
|
+
* Add `sandbox=""` attribute to all `<iframe>` elements in the editor content
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export function sandboxIframesInContent(jodit, nodeElm, hadEffect) {
|
|
13
|
+
if (!jodit.o.cleanHTML.sandboxIframesInContent ||
|
|
14
|
+
!Dom.isElement(nodeElm) ||
|
|
15
|
+
nodeElm.nodeName !== 'IFRAME') {
|
|
16
|
+
return hadEffect;
|
|
17
|
+
}
|
|
18
|
+
const elm = nodeElm;
|
|
19
|
+
if (!elm.hasAttribute('sandbox')) {
|
|
20
|
+
attr(elm, 'sandbox', '');
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return hadEffect;
|
|
24
|
+
}
|
|
@@ -9,11 +9,16 @@ import { sanitizeHTMLElement } from "../../../../../core/helpers/index.js";
|
|
|
9
9
|
* @private
|
|
10
10
|
*/
|
|
11
11
|
export function sanitizeAttributes(jodit, nodeElm, hadEffect) {
|
|
12
|
-
if (Dom.isElement(nodeElm)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
if (!Dom.isElement(nodeElm)) {
|
|
13
|
+
return hadEffect;
|
|
14
|
+
}
|
|
15
|
+
const opts = jodit.options.cleanHTML;
|
|
16
|
+
if (sanitizeHTMLElement(nodeElm, {
|
|
17
|
+
safeJavaScriptLink: opts.safeJavaScriptLink,
|
|
18
|
+
removeOnError: opts.removeOnError,
|
|
19
|
+
removeEventAttributes: opts.removeEventAttributes,
|
|
20
|
+
safeLinksTarget: opts.safeLinksTarget
|
|
21
|
+
})) {
|
|
17
22
|
return true;
|
|
18
23
|
}
|
|
19
24
|
return hadEffect;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/clean-html
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../../../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* Filter CSS properties in style attributes based on allowedStyles whitelist
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
export declare function sanitizeStyles(jodit: IJodit, nodeElm: Node, hadEffect: boolean): boolean;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { Dom } from "../../../../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../../../../core/helpers/utils/attr.js";
|
|
8
|
+
/**
|
|
9
|
+
* Filter CSS properties in style attributes based on allowedStyles whitelist
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export function sanitizeStyles(jodit, nodeElm, hadEffect) {
|
|
13
|
+
const allowedStyles = jodit.o.cleanHTML.allowedStyles;
|
|
14
|
+
if (!allowedStyles || !Dom.isElement(nodeElm)) {
|
|
15
|
+
return hadEffect;
|
|
16
|
+
}
|
|
17
|
+
const elm = nodeElm;
|
|
18
|
+
const style = attr(elm, 'style');
|
|
19
|
+
if (!style) {
|
|
20
|
+
return hadEffect;
|
|
21
|
+
}
|
|
22
|
+
const tagName = nodeElm.nodeName.toLowerCase();
|
|
23
|
+
const allowed = getAllowedPropsForTag(tagName, allowedStyles);
|
|
24
|
+
if (!allowed) {
|
|
25
|
+
return hadEffect;
|
|
26
|
+
}
|
|
27
|
+
const filtered = filterStyleProperties(style, allowed);
|
|
28
|
+
if (filtered !== style) {
|
|
29
|
+
attr(elm, 'style', filtered || null);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return hadEffect;
|
|
33
|
+
}
|
|
34
|
+
function getAllowedPropsForTag(tagName, allowedStyles) {
|
|
35
|
+
const tagSpecific = allowedStyles[tagName];
|
|
36
|
+
const global = allowedStyles['*'];
|
|
37
|
+
if (!tagSpecific && !global) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const set = new Set();
|
|
41
|
+
if (global) {
|
|
42
|
+
for (const prop of global) {
|
|
43
|
+
set.add(prop.toLowerCase());
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (tagSpecific) {
|
|
47
|
+
for (const prop of tagSpecific) {
|
|
48
|
+
set.add(prop.toLowerCase());
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return set;
|
|
52
|
+
}
|
|
53
|
+
function filterStyleProperties(style, allowed) {
|
|
54
|
+
return style
|
|
55
|
+
.split(';')
|
|
56
|
+
.map(s => s.trim())
|
|
57
|
+
.filter(s => {
|
|
58
|
+
if (!s) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const colonIdx = s.indexOf(':');
|
|
62
|
+
if (colonIdx === -1) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const prop = s.substring(0, colonIdx).trim().toLowerCase();
|
|
66
|
+
return allowed.has(prop);
|
|
67
|
+
})
|
|
68
|
+
.join('; ')
|
|
69
|
+
.replace(/;\s*$/, '');
|
|
70
|
+
}
|
|
@@ -132,7 +132,7 @@ export class dragAndDrop extends Plugin {
|
|
|
132
132
|
? ['a', 'href']
|
|
133
133
|
: ['img', 'src'];
|
|
134
134
|
fragment = this.j.createInside.element(tagName);
|
|
135
|
-
fragment
|
|
135
|
+
attr(fragment, field, attr(this.draggable, 'data-src') ||
|
|
136
136
|
attr(this.draggable, 'src') ||
|
|
137
137
|
'');
|
|
138
138
|
if (tagName === 'a') {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
6
|
import { Dom } from "../../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../../core/helpers/utils/attr.js";
|
|
7
8
|
import { scrollIntoViewIfNeeded } from "../../../core/helpers/utils/scroll-into-view.js";
|
|
8
9
|
/**
|
|
9
10
|
* Insert default paragraph
|
|
@@ -15,7 +16,7 @@ export function insertParagraph(fake, editor, wrapperTag, style) {
|
|
|
15
16
|
p.appendChild(br);
|
|
16
17
|
}
|
|
17
18
|
if (style && style.cssText) {
|
|
18
|
-
p
|
|
19
|
+
attr(p, 'style', style.cssText);
|
|
19
20
|
}
|
|
20
21
|
Dom.after(fake, p);
|
|
21
22
|
Dom.before(isBR ? p : br, fake);
|
package/esm/plugins/file/file.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Dom } from "../../core/dom/dom.js";
|
|
7
7
|
import { pluginSystem } from "../../core/global.js";
|
|
8
|
+
import { attr } from "../../core/helpers/utils/attr.js";
|
|
8
9
|
import { Config } from "../../config.js";
|
|
9
10
|
import { FileSelectorWidget } from "../../modules/widget/index.js";
|
|
10
11
|
Config.prototype.controls.file = {
|
|
@@ -29,8 +30,8 @@ Config.prototype.controls.file = {
|
|
|
29
30
|
upload: true,
|
|
30
31
|
url: (url, text) => {
|
|
31
32
|
if (sourceAnchor) {
|
|
32
|
-
sourceAnchor
|
|
33
|
-
sourceAnchor
|
|
33
|
+
attr(sourceAnchor, 'href', url);
|
|
34
|
+
attr(sourceAnchor, 'title', text);
|
|
34
35
|
}
|
|
35
36
|
else {
|
|
36
37
|
insert(url, text);
|
|
@@ -39,8 +39,8 @@ export function iframe(editor) {
|
|
|
39
39
|
if (opt.iframeCSSLinks) {
|
|
40
40
|
opt.iframeCSSLinks.forEach(href => {
|
|
41
41
|
const link = doc.createElement('link');
|
|
42
|
-
link
|
|
43
|
-
link
|
|
42
|
+
attr(link, 'rel', 'stylesheet');
|
|
43
|
+
attr(link, 'href', href);
|
|
44
44
|
doc.head && doc.head.appendChild(link);
|
|
45
45
|
});
|
|
46
46
|
}
|
|
@@ -58,11 +58,13 @@ export function iframe(editor) {
|
|
|
58
58
|
iframe.style.display = 'block';
|
|
59
59
|
iframe.src = 'about:blank';
|
|
60
60
|
iframe.className = 'jodit-wysiwyg_iframe';
|
|
61
|
-
iframe
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
attr(iframe, {
|
|
62
|
+
allowtransparency: 'true',
|
|
63
|
+
tabindex: opt.tabIndex.toString(),
|
|
64
|
+
frameborder: '0'
|
|
65
|
+
});
|
|
64
66
|
if (opt.iframeSandbox != null) {
|
|
65
|
-
iframe
|
|
67
|
+
attr(iframe, 'sandbox', opt.iframeSandbox);
|
|
66
68
|
}
|
|
67
69
|
editor.workplace.appendChild(iframe);
|
|
68
70
|
editor.iframe = iframe;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { Dom } from "../../core/dom/index.js";
|
|
7
7
|
import { pluginSystem } from "../../core/global.js";
|
|
8
8
|
import { $$ } from "../../core/helpers/index.js";
|
|
9
|
+
import { attr } from "../../core/helpers/utils/attr.js";
|
|
9
10
|
import { Icon } from "../../core/ui/icon.js";
|
|
10
11
|
import { Config } from "../../config.js";
|
|
11
12
|
import { FileSelectorWidget } from "../../modules/widget/index.js";
|
|
@@ -37,8 +38,8 @@ Config.prototype.controls.image = {
|
|
|
37
38
|
url = '//' + url;
|
|
38
39
|
}
|
|
39
40
|
const image = sourceImage || editor.createInside.element('img');
|
|
40
|
-
image
|
|
41
|
-
image
|
|
41
|
+
attr(image, 'src', url);
|
|
42
|
+
attr(image, 'alt', text);
|
|
42
43
|
if (!sourceImage) {
|
|
43
44
|
await editor.s.insertImage(image, null, editor.o.imageDefaultWidth);
|
|
44
45
|
}
|
|
@@ -15,6 +15,12 @@ export function applyLink(j, image, imageLink, imageLinkOpenInNewTab) {
|
|
|
15
15
|
}
|
|
16
16
|
attr(link, 'href', imageLink);
|
|
17
17
|
attr(link, 'target', imageLinkOpenInNewTab ? '_blank' : null);
|
|
18
|
+
if (!imageLinkOpenInNewTab) {
|
|
19
|
+
const relParts = (attr(link, 'rel') || '')
|
|
20
|
+
.split(/\s+/)
|
|
21
|
+
.filter(p => p && p !== 'noopener' && p !== 'noreferrer');
|
|
22
|
+
attr(link, 'rel', relParts.length ? relParts.join(' ') : null);
|
|
23
|
+
}
|
|
18
24
|
}
|
|
19
25
|
else {
|
|
20
26
|
if (link && link.parentNode) {
|
package/esm/plugins/link/link.js
CHANGED
|
@@ -90,7 +90,7 @@ export class link extends Plugin {
|
|
|
90
90
|
}
|
|
91
91
|
if (jodit.s.isCollapsed()) {
|
|
92
92
|
const a = jodit.createInside.element('a');
|
|
93
|
-
a
|
|
93
|
+
attr(a, 'href', html);
|
|
94
94
|
a.textContent = html;
|
|
95
95
|
jodit.e.fire('applyLink', jodit, a, null);
|
|
96
96
|
return a;
|
|
@@ -155,7 +155,9 @@ export class link extends Plugin {
|
|
|
155
155
|
target_checkbox.checked = attr(link, 'target') === '_blank';
|
|
156
156
|
}
|
|
157
157
|
if (noFollowCheckbox && nofollow_checkbox) {
|
|
158
|
-
nofollow_checkbox.checked = attr(link, 'rel')
|
|
158
|
+
nofollow_checkbox.checked = (attr(link, 'rel') || '')
|
|
159
|
+
.split(/\s+/)
|
|
160
|
+
.includes('nofollow');
|
|
159
161
|
}
|
|
160
162
|
insert.textContent = i18n('Update');
|
|
161
163
|
}
|
|
@@ -219,7 +221,17 @@ export class link extends Plugin {
|
|
|
219
221
|
attr(a, 'target', target_checkbox.checked ? '_blank' : null);
|
|
220
222
|
}
|
|
221
223
|
if (noFollowCheckbox && nofollow_checkbox) {
|
|
222
|
-
attr(a, 'rel'
|
|
224
|
+
const relParts = (attr(a, 'rel') || '')
|
|
225
|
+
.split(/\s+/)
|
|
226
|
+
.filter(Boolean);
|
|
227
|
+
const hasNofollow = relParts.includes('nofollow');
|
|
228
|
+
if (nofollow_checkbox.checked && !hasNofollow) {
|
|
229
|
+
relParts.push('nofollow');
|
|
230
|
+
}
|
|
231
|
+
else if (!nofollow_checkbox.checked && hasNofollow) {
|
|
232
|
+
relParts.splice(relParts.indexOf('nofollow'), 1);
|
|
233
|
+
}
|
|
234
|
+
attr(a, 'rel', relParts.length ? relParts.join(' ') : null);
|
|
223
235
|
}
|
|
224
236
|
jodit.e.fire('applyLink', jodit, a, form);
|
|
225
237
|
});
|
|
@@ -366,8 +366,8 @@ export class resizer extends Plugin {
|
|
|
366
366
|
})
|
|
367
367
|
.off(element, 'changesize')
|
|
368
368
|
.on(element, 'changesize', () => {
|
|
369
|
-
iframe
|
|
370
|
-
iframe
|
|
369
|
+
attr(iframe, 'width', element.offsetWidth + 'px');
|
|
370
|
+
attr(iframe, 'height', element.offsetHeight + 'px');
|
|
371
371
|
});
|
|
372
372
|
}
|
|
373
373
|
this.j.e.on(element, 'dragstart', this.hide);
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
6
|
import { Dom } from "../../../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../../../core/helpers/utils/attr.js";
|
|
7
8
|
import { css } from "../../../../core/helpers/utils/css.js";
|
|
8
9
|
import { SourceEditor } from "../sourceEditor.js";
|
|
9
10
|
export class TextAreaEditor extends SourceEditor {
|
|
@@ -73,15 +74,10 @@ export class TextAreaEditor extends SourceEditor {
|
|
|
73
74
|
this.instance.blur();
|
|
74
75
|
}
|
|
75
76
|
setPlaceHolder(title) {
|
|
76
|
-
this.instance
|
|
77
|
+
attr(this.instance, 'placeholder', title);
|
|
77
78
|
}
|
|
78
79
|
setReadOnly(isReadOnly) {
|
|
79
|
-
|
|
80
|
-
this.instance.setAttribute('readonly', 'true');
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
this.instance.removeAttribute('readonly');
|
|
84
|
-
}
|
|
80
|
+
attr(this.instance, 'readonly', isReadOnly ? 'true' : null);
|
|
85
81
|
}
|
|
86
82
|
selectAll() {
|
|
87
83
|
this.instance.select();
|
package/package.json
CHANGED
package/types/config.d.ts
CHANGED
|
@@ -947,13 +947,98 @@ interface Config {
|
|
|
947
947
|
*/
|
|
948
948
|
useIframeSandbox: boolean;
|
|
949
949
|
/**
|
|
950
|
+
* @deprecated Use `removeEventAttributes` instead
|
|
950
951
|
* Remove onError attributes
|
|
951
952
|
*/
|
|
952
953
|
removeOnError: boolean;
|
|
954
|
+
/**
|
|
955
|
+
* Remove all `on*` event handler attributes (onerror, onclick, onload, onmouseover, etc.)
|
|
956
|
+
* When enabled, this replaces the legacy `removeOnError` behavior with comprehensive protection.
|
|
957
|
+
*
|
|
958
|
+
* ```javascript
|
|
959
|
+
* Jodit.make('#editor', {
|
|
960
|
+
* cleanHTML: {
|
|
961
|
+
* removeEventAttributes: true
|
|
962
|
+
* }
|
|
963
|
+
* });
|
|
964
|
+
* ```
|
|
965
|
+
*/
|
|
966
|
+
removeEventAttributes: boolean;
|
|
953
967
|
/**
|
|
954
968
|
* Safe href="javascript:" links
|
|
955
969
|
*/
|
|
956
970
|
safeJavaScriptLink: boolean;
|
|
971
|
+
/**
|
|
972
|
+
* Automatically add `rel="noopener noreferrer"` to links with `target="_blank"`
|
|
973
|
+
*
|
|
974
|
+
* ```javascript
|
|
975
|
+
* Jodit.make('#editor', {
|
|
976
|
+
* cleanHTML: {
|
|
977
|
+
* safeLinksTarget: true
|
|
978
|
+
* }
|
|
979
|
+
* });
|
|
980
|
+
* ```
|
|
981
|
+
*/
|
|
982
|
+
safeLinksTarget: boolean;
|
|
983
|
+
/**
|
|
984
|
+
* Whitelist of allowed CSS properties inside `style` attributes.
|
|
985
|
+
* If set, all CSS properties not in the list will be removed.
|
|
986
|
+
*
|
|
987
|
+
* ```javascript
|
|
988
|
+
* Jodit.make('#editor', {
|
|
989
|
+
* cleanHTML: {
|
|
990
|
+
* allowedStyles: {
|
|
991
|
+
* '*': ['color', 'background-color', 'font-size', 'text-align'],
|
|
992
|
+
* img: ['width', 'height']
|
|
993
|
+
* }
|
|
994
|
+
* }
|
|
995
|
+
* });
|
|
996
|
+
* ```
|
|
997
|
+
*/
|
|
998
|
+
allowedStyles: false | IDictionary<string[]>;
|
|
999
|
+
/**
|
|
1000
|
+
* Custom sanitizer function. Called after Jodit's built-in sanitization.
|
|
1001
|
+
* Use this to integrate DOMPurify or other external sanitizers.
|
|
1002
|
+
*
|
|
1003
|
+
* ```javascript
|
|
1004
|
+
* import DOMPurify from 'dompurify';
|
|
1005
|
+
*
|
|
1006
|
+
* Jodit.make('#editor', {
|
|
1007
|
+
* cleanHTML: {
|
|
1008
|
+
* sanitizer: (html) => DOMPurify.sanitize(html)
|
|
1009
|
+
* }
|
|
1010
|
+
* });
|
|
1011
|
+
* ```
|
|
1012
|
+
*/
|
|
1013
|
+
sanitizer: false | ((value: string) => string);
|
|
1014
|
+
/**
|
|
1015
|
+
* Automatically add `sandbox=""` attribute to all `<iframe>` elements in editor content.
|
|
1016
|
+
* Prevents embedded content from running scripts or accessing the parent page.
|
|
1017
|
+
*
|
|
1018
|
+
* ```javascript
|
|
1019
|
+
* Jodit.make('#editor', {
|
|
1020
|
+
* cleanHTML: {
|
|
1021
|
+
* sandboxIframesInContent: true
|
|
1022
|
+
* }
|
|
1023
|
+
* });
|
|
1024
|
+
* ```
|
|
1025
|
+
*/
|
|
1026
|
+
sandboxIframesInContent: boolean;
|
|
1027
|
+
/**
|
|
1028
|
+
* Convert unsafe embed elements to sandboxed `<iframe>`.
|
|
1029
|
+
* - `['object', 'embed']` — default
|
|
1030
|
+
* - `false` — disabled
|
|
1031
|
+
* - `string[]` — custom list of tag names to convert
|
|
1032
|
+
*
|
|
1033
|
+
* ```javascript
|
|
1034
|
+
* Jodit.make('#editor', {
|
|
1035
|
+
* cleanHTML: {
|
|
1036
|
+
* convertUnsafeEmbeds: Jodit.atom(['object', 'embed', 'applet'])
|
|
1037
|
+
* }
|
|
1038
|
+
* });
|
|
1039
|
+
* ```
|
|
1040
|
+
*/
|
|
1041
|
+
convertUnsafeEmbeds: false | string[];
|
|
957
1042
|
/**
|
|
958
1043
|
* The allowTags option defines which elements will remain in the
|
|
959
1044
|
* edited text when the editor saves. You can use this limit the returned HTML.
|
package/types/core/dom/dom.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export declare class Dom {
|
|
|
52
52
|
*/
|
|
53
53
|
static replace<T extends HTMLElement>(elm: Node, newTagName: HTMLTagNames): T;
|
|
54
54
|
static replace<T extends HTMLElement>(elm: Node, newTagName: HTMLTagNames, create: ICreate, withAttributes?: boolean, notMoveContent?: boolean): T;
|
|
55
|
+
static replace<T extends Node>(elm: Node, newTagName: T): T;
|
|
55
56
|
static replace<T extends Node>(elm: Node, newTagName: T | string, create?: ICreate, withAttributes?: boolean, notMoveContent?: boolean): T;
|
|
56
57
|
/**
|
|
57
58
|
* Checks whether the Node text and blank (in this case it may contain invisible auxiliary characters ,
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
-
type safeOptions = {
|
|
6
|
+
export type safeOptions = {
|
|
7
7
|
removeOnError: boolean;
|
|
8
8
|
safeJavaScriptLink: boolean;
|
|
9
|
+
removeEventAttributes?: boolean;
|
|
10
|
+
safeLinksTarget?: boolean;
|
|
9
11
|
};
|
|
10
12
|
/**
|
|
11
13
|
* Removes dangerous constructs from HTML
|
|
12
14
|
*/
|
|
13
15
|
export declare function safeHTML(box: HTMLElement | DocumentFragment, options: safeOptions): void;
|
|
14
16
|
export declare function sanitizeHTMLElement(elm: Element | DocumentFragment, { safeJavaScriptLink, removeOnError }?: safeOptions): boolean;
|
|
15
|
-
export {};
|