@elementor/editor-canvas 4.3.0-1019 → 4.3.0-1021

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/dist/index.js CHANGED
@@ -2578,28 +2578,13 @@ function createDomRenderer() {
2578
2578
  render: environment.render
2579
2579
  };
2580
2580
  }
2581
+ function getAllowedHtmlWrapperTags() {
2582
+ return window.elementorCommon?.config?.allowedHTMLWrapperTags ?? [];
2583
+ }
2581
2584
  function escapeHtmlTag(value) {
2582
- const allowedTags = [
2583
- "a",
2584
- "article",
2585
- "aside",
2586
- "button",
2587
- "div",
2588
- "footer",
2589
- "h1",
2590
- "h2",
2591
- "h3",
2592
- "h4",
2593
- "h5",
2594
- "h6",
2595
- "header",
2596
- "main",
2597
- "nav",
2598
- "p",
2599
- "section",
2600
- "span"
2601
- ];
2602
- return allowedTags.includes(value) ? value : "div";
2585
+ const allowedTags = getAllowedHtmlWrapperTags();
2586
+ const normalizedTag = value?.toLowerCase?.() ?? "";
2587
+ return allowedTags.includes(normalizedTag) ? value : "div";
2603
2588
  }
2604
2589
  function escapeURL(value) {
2605
2590
  const allowedProtocols = ["http:", "https:", "mailto:", "tel:"];
package/dist/index.mjs CHANGED
@@ -2530,28 +2530,13 @@ function createDomRenderer() {
2530
2530
  render: environment.render
2531
2531
  };
2532
2532
  }
2533
+ function getAllowedHtmlWrapperTags() {
2534
+ return window.elementorCommon?.config?.allowedHTMLWrapperTags ?? [];
2535
+ }
2533
2536
  function escapeHtmlTag(value) {
2534
- const allowedTags = [
2535
- "a",
2536
- "article",
2537
- "aside",
2538
- "button",
2539
- "div",
2540
- "footer",
2541
- "h1",
2542
- "h2",
2543
- "h3",
2544
- "h4",
2545
- "h5",
2546
- "h6",
2547
- "header",
2548
- "main",
2549
- "nav",
2550
- "p",
2551
- "section",
2552
- "span"
2553
- ];
2554
- return allowedTags.includes(value) ? value : "div";
2537
+ const allowedTags = getAllowedHtmlWrapperTags();
2538
+ const normalizedTag = value?.toLowerCase?.() ?? "";
2539
+ return allowedTags.includes(normalizedTag) ? value : "div";
2555
2540
  }
2556
2541
  function escapeURL(value) {
2557
2542
  const allowedProtocols = ["http:", "https:", "mailto:", "tel:"];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-canvas",
3
3
  "description": "Elementor Editor Canvas",
4
- "version": "4.3.0-1019",
4
+ "version": "4.3.0-1021",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,26 +37,26 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "4.3.0-1019",
41
- "@elementor/editor-controls": "4.3.0-1019",
42
- "@elementor/editor-documents": "4.3.0-1019",
43
- "@elementor/editor-elements": "4.3.0-1019",
44
- "@elementor/editor-interactions": "4.3.0-1019",
45
- "@elementor/editor-mcp": "4.3.0-1019",
46
- "@elementor/editor-notifications": "4.3.0-1019",
47
- "@elementor/editor-props": "4.3.0-1019",
48
- "@elementor/editor-responsive": "4.3.0-1019",
49
- "@elementor/editor-styles": "4.3.0-1019",
50
- "@elementor/editor-styles-repository": "4.3.0-1019",
51
- "@elementor/editor-ui": "4.3.0-1019",
52
- "@elementor/editor-v1-adapters": "4.3.0-1019",
53
- "@elementor/events": "4.3.0-1019",
54
- "@elementor/http-client": "4.3.0-1019",
55
- "@elementor/schema": "4.3.0-1019",
56
- "@elementor/twing": "4.3.0-1019",
40
+ "@elementor/editor": "4.3.0-1021",
41
+ "@elementor/editor-controls": "4.3.0-1021",
42
+ "@elementor/editor-documents": "4.3.0-1021",
43
+ "@elementor/editor-elements": "4.3.0-1021",
44
+ "@elementor/editor-interactions": "4.3.0-1021",
45
+ "@elementor/editor-mcp": "4.3.0-1021",
46
+ "@elementor/editor-notifications": "4.3.0-1021",
47
+ "@elementor/editor-props": "4.3.0-1021",
48
+ "@elementor/editor-responsive": "4.3.0-1021",
49
+ "@elementor/editor-styles": "4.3.0-1021",
50
+ "@elementor/editor-styles-repository": "4.3.0-1021",
51
+ "@elementor/editor-ui": "4.3.0-1021",
52
+ "@elementor/editor-v1-adapters": "4.3.0-1021",
53
+ "@elementor/events": "4.3.0-1021",
54
+ "@elementor/http-client": "4.3.0-1021",
55
+ "@elementor/schema": "4.3.0-1021",
56
+ "@elementor/twing": "4.3.0-1021",
57
57
  "@elementor/ui": "1.37.5",
58
- "@elementor/utils": "4.3.0-1019",
59
- "@elementor/wp-media": "4.3.0-1019",
58
+ "@elementor/utils": "4.3.0-1021",
59
+ "@elementor/wp-media": "4.3.0-1021",
60
60
  "@floating-ui/react": "^0.27.5",
61
61
  "@wordpress/i18n": "^5.13.0",
62
62
  "dompurify": "^3.2.6"
@@ -1,7 +1,21 @@
1
1
  /* eslint-disable testing-library/render-result-naming-convention */
2
2
  import { createDomRenderer } from '../create-dom-renderer';
3
3
 
4
+ const TEST_ALLOWED_HTML_WRAPPER_TAGS = [ 'a', 'div', 'form', 'span' ];
5
+
4
6
  describe( 'createDomRenderer', () => {
7
+ beforeEach( () => {
8
+ window.elementorCommon = {
9
+ config: {
10
+ allowedHTMLWrapperTags: TEST_ALLOWED_HTML_WRAPPER_TAGS,
11
+ },
12
+ };
13
+ } );
14
+
15
+ afterEach( () => {
16
+ delete window.elementorCommon;
17
+ } );
18
+
5
19
  it.each( [
6
20
  {
7
21
  title: 'basic string',
@@ -15,12 +29,24 @@ describe( 'createDomRenderer', () => {
15
29
  context: { tag: 'a' },
16
30
  expected: '<a></a>',
17
31
  },
32
+ {
33
+ title: 'allowed form html tag',
34
+ template: `<{{ tag | e( 'html_tag' ) }}></{{ tag | e( 'html_tag' ) }}>`,
35
+ context: { tag: 'form' },
36
+ expected: '<form></form>',
37
+ },
18
38
  {
19
39
  title: 'disallowed html tags',
20
40
  template: `<{{ tag | e( 'html_tag' ) }}></{{ tag | e( 'html_tag' ) }}>`,
21
41
  context: { tag: 'script' },
22
42
  expected: '<div></div>',
23
43
  },
44
+ {
45
+ title: 'allowed html tag with uppercase casing',
46
+ template: `<{{ tag | e( 'html_tag' ) }}></{{ tag | e( 'html_tag' ) }}>`,
47
+ context: { tag: 'DIV' },
48
+ expected: '<DIV></DIV>',
49
+ },
24
50
  {
25
51
  title: 'allowed url (http)',
26
52
  template: `{{ url | e( 'full_url' ) }}`,
@@ -63,4 +89,38 @@ describe( 'createDomRenderer', () => {
63
89
  // Assert.
64
90
  expect( result ).toBe( expected );
65
91
  } );
92
+
93
+ it( 'should validate a tag added via localized config', async () => {
94
+ // Arrange.
95
+ window.elementorCommon = {
96
+ config: {
97
+ allowedHTMLWrapperTags: [ ...TEST_ALLOWED_HTML_WRAPPER_TAGS, 'custom-tag' ],
98
+ },
99
+ };
100
+ const domRenderer = createDomRenderer();
101
+ const template = `<{{ tag | e( 'html_tag' ) }}></{{ tag | e( 'html_tag' ) }}>`;
102
+
103
+ domRenderer.register( 'test-template', template );
104
+
105
+ // Act.
106
+ const result = await domRenderer.render( 'test-template', { tag: 'custom-tag' } );
107
+
108
+ // Assert.
109
+ expect( result ).toBe( '<custom-tag></custom-tag>' );
110
+ } );
111
+
112
+ it( 'should fail closed to div when the localized config is missing, even for an otherwise-safe tag', async () => {
113
+ // Arrange.
114
+ delete window.elementorCommon;
115
+ const domRenderer = createDomRenderer();
116
+ const template = `<{{ tag | e( 'html_tag' ) }}></{{ tag | e( 'html_tag' ) }}>`;
117
+
118
+ domRenderer.register( 'test-template', template );
119
+
120
+ // Act.
121
+ const result = await domRenderer.render( 'test-template', { tag: 'a' } );
122
+
123
+ // Assert.
124
+ expect( result ).toBe( '<div></div>' );
125
+ } );
66
126
  } );
@@ -18,29 +18,20 @@ export function createDomRenderer(): DomRenderer {
18
18
  };
19
19
  }
20
20
 
21
+ /**
22
+ * PHP (`Utils::get_allowed_html_wrapper_tags()`) is the single source of truth for this
23
+ * list; it's localized via `elementorCommon.config`. If it's ever missing, fail closed
24
+ * (no tags allowed) rather than fall back to a second hardcoded copy that could drift.
25
+ */
26
+ function getAllowedHtmlWrapperTags(): readonly string[] {
27
+ return window.elementorCommon?.config?.allowedHTMLWrapperTags ?? [];
28
+ }
29
+
21
30
  function escapeHtmlTag( value: string ) {
22
- const allowedTags = [
23
- 'a',
24
- 'article',
25
- 'aside',
26
- 'button',
27
- 'div',
28
- 'footer',
29
- 'h1',
30
- 'h2',
31
- 'h3',
32
- 'h4',
33
- 'h5',
34
- 'h6',
35
- 'header',
36
- 'main',
37
- 'nav',
38
- 'p',
39
- 'section',
40
- 'span',
41
- ];
42
-
43
- return allowedTags.includes( value ) ? value : 'div';
31
+ const allowedTags = getAllowedHtmlWrapperTags();
32
+ const normalizedTag = value?.toLowerCase?.() ?? '';
33
+
34
+ return allowedTags.includes( normalizedTag ) ? value : 'div';
44
35
  }
45
36
 
46
37
  function escapeURL( value: string ) {