@elementor/editor-canvas 0.18.0 → 0.18.1

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.
@@ -0,0 +1,84 @@
1
+ import * as React from 'react';
2
+ import { createPortal } from 'react-dom';
3
+ import { createDOMElement } from 'test-utils';
4
+ import { render, renderHook } from '@testing-library/react';
5
+
6
+ import { getCanvasIframeDocument } from '../../sync/get-canvas-iframe-document';
7
+ import { useDocumentsCssLinks } from '../use-documents-css-links';
8
+
9
+ jest.mock( '../../sync/get-canvas-iframe-document', () => ( {
10
+ getCanvasIframeDocument: jest.fn(),
11
+ } ) );
12
+
13
+ describe( 'useDocumentsCssLinks', () => {
14
+ const head = createDOMElement( {
15
+ tag: 'head',
16
+ children: [
17
+ createDOMElement( {
18
+ tag: 'link',
19
+ attrs: { href: '2.css', rel: 'stylesheet', id: 'elementor-post-2-css' },
20
+ } ),
21
+ createDOMElement( {
22
+ tag: 'link',
23
+ attrs: { href: '10.css', rel: 'stylesheet', id: 'elementor-post-10-css' },
24
+ } ),
25
+ createDOMElement( {
26
+ tag: 'link',
27
+ attrs: { href: '5.css', rel: 'stylesheet', id: 'elementor-post-5-css' },
28
+ } ),
29
+ createDOMElement( {
30
+ tag: 'link',
31
+ attrs: { href: 'not-elementor.css', rel: 'stylesheet', id: 'not-elementor-css' },
32
+ } ),
33
+ ],
34
+ } );
35
+
36
+ const body = createDOMElement( {
37
+ tag: 'body',
38
+ children: [
39
+ createDOMElement( { tag: 'div', attrs: { 'data-elementor-id': '2' } } ),
40
+ createDOMElement( { tag: 'div', attrs: { 'data-elementor-id': '4' } } ),
41
+ createDOMElement( {
42
+ tag: 'div',
43
+ children: [ createDOMElement( { tag: 'div', attrs: { 'data-elementor-id': '5' } } ) ],
44
+ } ),
45
+ ],
46
+ } );
47
+
48
+ const Component = () => {
49
+ const links = useDocumentsCssLinks();
50
+
51
+ return createPortal(
52
+ <>
53
+ { links.map( ( link ) => (
54
+ <link key={ link.id } { ...link } data-from-hook />
55
+ ) ) }
56
+ </>,
57
+ head
58
+ );
59
+ };
60
+
61
+ it( 'should return an array of links attrs and remove them from the dom', () => {
62
+ // Arrange.
63
+ const document = { body, head };
64
+
65
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( document as never );
66
+
67
+ // Act.
68
+ render( <Component /> );
69
+
70
+ // Assert.
71
+ expect( head ).toMatchSnapshot();
72
+ } );
73
+
74
+ it( 'should return empty array when iframe document is not available', () => {
75
+ // Arrange.
76
+ jest.mocked( getCanvasIframeDocument ).mockReturnValue( null );
77
+
78
+ // Act.
79
+ const { result } = renderHook( () => useDocumentsCssLinks(), { initialProps: {} } );
80
+
81
+ // Assert.
82
+ expect( result.current ).toEqual( [] );
83
+ } );
84
+ } );
@@ -0,0 +1,58 @@
1
+ import { __privateUseListenTo as useListenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
2
+
3
+ import { getCanvasIframeDocument } from '../sync/get-canvas-iframe-document';
4
+
5
+ const REMOVED_ATTR = 'data-e-removed';
6
+ const DOCUMENT_WRAPPER_ATTR = 'data-elementor-id';
7
+ const CSS_LINK_ID_PREFIX = 'elementor-post-';
8
+ const CSS_LINK_ID_SUFFIX = '-css';
9
+
10
+ export function useDocumentsCssLinks() {
11
+ return useListenTo( commandEndEvent( 'editor/documents/attach-preview' ), () => {
12
+ const iframeDocument = getCanvasIframeDocument();
13
+
14
+ if ( ! iframeDocument ) {
15
+ return [];
16
+ }
17
+
18
+ const relevantLinkIds = getDocumentsIdsInCanvas( iframeDocument ).map(
19
+ ( id ) => `${ CSS_LINK_ID_PREFIX }${ id }${ CSS_LINK_ID_SUFFIX }`
20
+ );
21
+
22
+ const links = getDocumentsCssLinks( iframeDocument ).filter( ( link ) =>
23
+ relevantLinkIds.includes( link.getAttribute( 'id' ) ?? '' )
24
+ );
25
+
26
+ links.forEach( ( link ) => {
27
+ if ( ! link.hasAttribute( REMOVED_ATTR ) ) {
28
+ link.remove();
29
+ }
30
+ } );
31
+
32
+ return links.map( ( link ) => ( {
33
+ ...getLinkAttrs( link ),
34
+ id: link.getAttribute( 'id' ) ?? '',
35
+ [ REMOVED_ATTR ]: true,
36
+ } ) );
37
+ } );
38
+ }
39
+
40
+ function getDocumentsIdsInCanvas( document: Document ) {
41
+ return [ ...( document.body.querySelectorAll< HTMLElement >( `[${ DOCUMENT_WRAPPER_ATTR }]` ) ?? [] ) ].map(
42
+ ( el ) => el.getAttribute( DOCUMENT_WRAPPER_ATTR ) || ''
43
+ );
44
+ }
45
+
46
+ function getDocumentsCssLinks( document: Document ) {
47
+ return [
48
+ ...( document.head.querySelectorAll< HTMLLinkElement >(
49
+ `link[rel="stylesheet"][id^=${ CSS_LINK_ID_PREFIX }][id$=${ CSS_LINK_ID_SUFFIX }]`
50
+ ) ?? [] ),
51
+ ];
52
+ }
53
+
54
+ function getLinkAttrs( el: HTMLLinkElement ) {
55
+ const entries = [ ...el.attributes ].map( ( attr ) => [ attr.name, attr.value ] as const );
56
+
57
+ return Object.fromEntries( entries );
58
+ }
@@ -1,7 +1,7 @@
1
1
  import type { CanvasExtendedWindow } from './types';
2
2
 
3
- export function getCanvasIframeHead() {
3
+ export function getCanvasIframeDocument() {
4
4
  const extendedWindow = window as unknown as CanvasExtendedWindow;
5
5
 
6
- return extendedWindow.elementor?.$preview?.[ 0 ]?.contentDocument?.head;
6
+ return extendedWindow.elementor?.$preview?.[ 0 ]?.contentDocument;
7
7
  }