@squiz/formatted-text-editor 2.1.0 → 2.2.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/CHANGELOG.md +18 -0
- package/demo/App.tsx +5 -0
- package/demo/AppContext.tsx +107 -70
- package/lib/EditorToolbar/FloatingToolbar.js +1 -1
- package/lib/EditorToolbar/Tools/Image/Form/ImageForm.d.ts +2 -1
- package/lib/EditorToolbar/Tools/Image/Form/ImageForm.js +53 -10
- package/lib/EditorToolbar/Tools/Image/ImageButton.js +8 -5
- package/lib/EditorToolbar/Tools/Image/ImageModal.js +3 -1
- package/lib/Extensions/Extensions.d.ts +1 -0
- package/lib/Extensions/Extensions.js +3 -0
- package/lib/Extensions/FetchUrlExtension/FetchUrlExtension.js +6 -0
- package/lib/Extensions/ImageExtension/DAMImageExtension.d.ts +17 -0
- package/lib/Extensions/ImageExtension/DAMImageExtension.js +97 -0
- package/lib/ui/Fields/ResourceBrowserSelector/ResourceBrowserSelector.d.ts +28 -0
- package/lib/ui/Fields/ResourceBrowserSelector/ResourceBrowserSelector.js +88 -0
- package/lib/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.js +9 -0
- package/lib/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.js +9 -0
- package/package.json +4 -2
- package/src/EditorToolbar/FloatingToolbar.spec.tsx +3 -1
- package/src/EditorToolbar/FloatingToolbar.tsx +1 -1
- package/src/EditorToolbar/Tools/Image/Form/ImageForm.spec.tsx +27 -2
- package/src/EditorToolbar/Tools/Image/Form/ImageForm.tsx +61 -14
- package/src/EditorToolbar/Tools/Image/ImageButton.spec.tsx +70 -2
- package/src/EditorToolbar/Tools/Image/ImageButton.tsx +12 -6
- package/src/EditorToolbar/Tools/Image/ImageModal.tsx +4 -1
- package/src/Extensions/Extensions.ts +3 -0
- package/src/Extensions/FetchUrlExtension/FetchUrlExtension.ts +9 -0
- package/src/Extensions/ImageExtension/DAMImageExtension.spec.ts +87 -0
- package/src/Extensions/ImageExtension/DAMImageExtension.ts +119 -0
- package/src/ui/Fields/ResourceBrowserSelector/ResourceBrowserSelector.spec.tsx +219 -0
- package/src/ui/Fields/ResourceBrowserSelector/ResourceBrowserSelector.tsx +109 -0
- package/src/utils/converters/mocks/squizNodeJson.mock.ts +21 -0
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.ts +10 -0
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.ts +8 -0
- package/src/utils/getNodeNamesByGroup.spec.ts +1 -0
- package/tests/index.ts +1 -0
- package/tests/mockResourceBrowser.tsx +46 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
import {
|
2
|
+
ApplySchemaAttributes,
|
3
|
+
command,
|
4
|
+
extension,
|
5
|
+
ExtensionPriority,
|
6
|
+
ExtensionTag,
|
7
|
+
isElementDomNode,
|
8
|
+
NodeExtension,
|
9
|
+
NodeExtensionSpec,
|
10
|
+
NodeSpecOverride,
|
11
|
+
omitExtraAttributes,
|
12
|
+
CommandFunction,
|
13
|
+
} from '@remirror/core';
|
14
|
+
import { getTextSelection } from 'remirror';
|
15
|
+
import { NodeName } from '../Extensions';
|
16
|
+
|
17
|
+
export type DAMImageAttributes = {
|
18
|
+
damObjectId: string;
|
19
|
+
damSystemIdentifier: string;
|
20
|
+
damSystemType: string;
|
21
|
+
damAdditional?: {
|
22
|
+
variant: string;
|
23
|
+
};
|
24
|
+
url: string;
|
25
|
+
};
|
26
|
+
|
27
|
+
@extension({
|
28
|
+
defaultOptions: {},
|
29
|
+
defaultPriority: ExtensionPriority.High,
|
30
|
+
})
|
31
|
+
export class DAMImageExtension extends NodeExtension {
|
32
|
+
get name() {
|
33
|
+
return NodeName.DAMImage as const;
|
34
|
+
}
|
35
|
+
|
36
|
+
createTags() {
|
37
|
+
return [ExtensionTag.InlineNode, ExtensionTag.Media];
|
38
|
+
}
|
39
|
+
|
40
|
+
createNodeSpec(extra: ApplySchemaAttributes, override: NodeSpecOverride): NodeExtensionSpec {
|
41
|
+
return {
|
42
|
+
inline: true,
|
43
|
+
draggable: true,
|
44
|
+
selectable: true,
|
45
|
+
...override,
|
46
|
+
attrs: {
|
47
|
+
...extra.defaults(),
|
48
|
+
damObjectId: {},
|
49
|
+
damSystemIdentifier: {},
|
50
|
+
damSystemType: {},
|
51
|
+
damAdditional: { default: undefined },
|
52
|
+
src: { default: '' },
|
53
|
+
},
|
54
|
+
parseDOM: [
|
55
|
+
{
|
56
|
+
tag: 'img[data-dam-object-id]',
|
57
|
+
getAttrs: (node) => {
|
58
|
+
if (!isElementDomNode(node)) {
|
59
|
+
return false;
|
60
|
+
}
|
61
|
+
|
62
|
+
const damObjectId = node.getAttribute('data-dam-object-id');
|
63
|
+
const damSystemIdentifier = node.getAttribute('data-dam-system-identifier');
|
64
|
+
const damSystemType = node.getAttribute('data-dam-system-type');
|
65
|
+
let damAdditional = node.getAttribute('data-dam-additional') || undefined;
|
66
|
+
|
67
|
+
if (!damObjectId || !damSystemIdentifier || !damSystemType) {
|
68
|
+
return false;
|
69
|
+
}
|
70
|
+
|
71
|
+
if (damAdditional) {
|
72
|
+
damAdditional = JSON.parse(damAdditional);
|
73
|
+
}
|
74
|
+
|
75
|
+
return {
|
76
|
+
...extra.parse(node),
|
77
|
+
damObjectId,
|
78
|
+
damSystemIdentifier,
|
79
|
+
damSystemType,
|
80
|
+
damAdditional,
|
81
|
+
src: '',
|
82
|
+
};
|
83
|
+
},
|
84
|
+
},
|
85
|
+
],
|
86
|
+
toDOM: (node) => {
|
87
|
+
const { damObjectId, damSystemIdentifier, damSystemType, damAdditional, src, ...rest } = omitExtraAttributes(
|
88
|
+
node.attrs,
|
89
|
+
extra,
|
90
|
+
);
|
91
|
+
|
92
|
+
return [
|
93
|
+
'img',
|
94
|
+
{
|
95
|
+
...extra.dom(node),
|
96
|
+
...rest,
|
97
|
+
src,
|
98
|
+
'data-dam-object-id': damObjectId,
|
99
|
+
'data-dam-system-identifier': damSystemIdentifier,
|
100
|
+
'data-dam-system-type': damSystemType,
|
101
|
+
'data-dam-additional': damAdditional ? JSON.stringify(damAdditional) : undefined,
|
102
|
+
},
|
103
|
+
];
|
104
|
+
},
|
105
|
+
};
|
106
|
+
}
|
107
|
+
|
108
|
+
@command()
|
109
|
+
insertDAMImage(attrs: DAMImageAttributes): CommandFunction {
|
110
|
+
return ({ tr, dispatch }) => {
|
111
|
+
const { from, to } = getTextSelection(tr.selection, tr.doc);
|
112
|
+
const node = this.type.create({ ...attrs, src: attrs.url });
|
113
|
+
|
114
|
+
dispatch?.(tr.replaceRangeWith(from, to, node));
|
115
|
+
|
116
|
+
return true;
|
117
|
+
};
|
118
|
+
}
|
119
|
+
}
|
@@ -0,0 +1,219 @@
|
|
1
|
+
import '@testing-library/jest-dom';
|
2
|
+
import React from 'react';
|
3
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
4
|
+
import { ResourceBrowserResource } from '@squiz/resource-browser';
|
5
|
+
import { ResourceBrowserSelector } from './ResourceBrowserSelector';
|
6
|
+
import { mockResourceBrowser } from '../../../../tests';
|
7
|
+
|
8
|
+
const resourceBrowserSpy = jest.fn();
|
9
|
+
const { setSelectedResource, setShouldUseMockResourceBrowser, mockResourceBrowserImpl } = mockResourceBrowser();
|
10
|
+
jest.mock('@squiz/resource-browser', () => ({
|
11
|
+
...jest.requireActual('@squiz/resource-browser'),
|
12
|
+
ResourceBrowser: (props: any) => {
|
13
|
+
resourceBrowserSpy(props);
|
14
|
+
return mockResourceBrowserImpl(props);
|
15
|
+
},
|
16
|
+
}));
|
17
|
+
setShouldUseMockResourceBrowser(true);
|
18
|
+
|
19
|
+
describe('ResourceBrowserSelector', () => {
|
20
|
+
it('Renders empty state when no value is provided', async () => {
|
21
|
+
render(<ResourceBrowserSelector modalTitle="Insert asset" onChange={jest.fn()} />);
|
22
|
+
|
23
|
+
expect(resourceBrowserSpy).toHaveBeenCalledWith(
|
24
|
+
expect.objectContaining({
|
25
|
+
value: null,
|
26
|
+
}),
|
27
|
+
);
|
28
|
+
});
|
29
|
+
|
30
|
+
it('AssetImage: Renders a selected state when a value is provided', async () => {
|
31
|
+
render(
|
32
|
+
<ResourceBrowserSelector
|
33
|
+
modalTitle="Insert asset"
|
34
|
+
value={{
|
35
|
+
matrixIdentifier: 'matrix-api-identifier',
|
36
|
+
matrixAssetId: 'my-resource-id',
|
37
|
+
addional: 'addditional data',
|
38
|
+
}}
|
39
|
+
onChange={jest.fn()}
|
40
|
+
/>,
|
41
|
+
);
|
42
|
+
|
43
|
+
expect(resourceBrowserSpy).toHaveBeenCalledWith(
|
44
|
+
expect.objectContaining({
|
45
|
+
value: {
|
46
|
+
resourceId: 'my-resource-id',
|
47
|
+
sourceId: 'matrix-api-identifier',
|
48
|
+
},
|
49
|
+
}),
|
50
|
+
);
|
51
|
+
});
|
52
|
+
|
53
|
+
it('DAMImage: Renders a selected state when a value is provided', async () => {
|
54
|
+
render(
|
55
|
+
<ResourceBrowserSelector
|
56
|
+
modalTitle="Insert asset"
|
57
|
+
value={{
|
58
|
+
damObjectId: '123-456-789',
|
59
|
+
damSystemIdentifier: 'zzz-xxx-ccc',
|
60
|
+
addional: 'addditional data',
|
61
|
+
}}
|
62
|
+
onChange={jest.fn()}
|
63
|
+
/>,
|
64
|
+
);
|
65
|
+
|
66
|
+
expect(resourceBrowserSpy).toHaveBeenCalledWith(
|
67
|
+
expect.objectContaining({
|
68
|
+
value: {
|
69
|
+
resourceId: '123-456-789',
|
70
|
+
sourceId: 'zzz-xxx-ccc',
|
71
|
+
},
|
72
|
+
}),
|
73
|
+
);
|
74
|
+
});
|
75
|
+
|
76
|
+
it('AssetImage: Calls onChange with expected value when resources is selected', async () => {
|
77
|
+
const handleChange = jest.fn();
|
78
|
+
setSelectedResource({
|
79
|
+
id: 'my-resource-id',
|
80
|
+
name: 'My resource',
|
81
|
+
url: 'myResourceUrl',
|
82
|
+
source: {
|
83
|
+
id: 'my-source-id',
|
84
|
+
type: 'matrix',
|
85
|
+
},
|
86
|
+
} as unknown as ResourceBrowserResource);
|
87
|
+
|
88
|
+
render(
|
89
|
+
<ResourceBrowserSelector
|
90
|
+
modalTitle="Insert asset"
|
91
|
+
value={{ matrixIdentifier: undefined, matrixAssetId: undefined, additional: 'additional data' }}
|
92
|
+
onChange={handleChange}
|
93
|
+
/>,
|
94
|
+
);
|
95
|
+
|
96
|
+
// Trigger the onChange handler to be called
|
97
|
+
await waitFor(() => {
|
98
|
+
expect(screen.getByRole('button', { name: 'Select ResourceBrowser Resource' })).toBeInTheDocument();
|
99
|
+
});
|
100
|
+
fireEvent.click(await screen.findByRole('button', { name: 'Select ResourceBrowser Resource' }));
|
101
|
+
|
102
|
+
expect(handleChange).toHaveBeenCalledWith({
|
103
|
+
target: {
|
104
|
+
value: {
|
105
|
+
additional: 'additional data',
|
106
|
+
matrixAssetId: 'my-resource-id',
|
107
|
+
matrixIdentifier: 'my-source-id',
|
108
|
+
url: 'myResourceUrl',
|
109
|
+
nodeType: 'assetImage',
|
110
|
+
},
|
111
|
+
},
|
112
|
+
});
|
113
|
+
});
|
114
|
+
|
115
|
+
it('DAMImage: Calls onChange with expected value when resources is selected', async () => {
|
116
|
+
const handleChange = jest.fn();
|
117
|
+
setSelectedResource({
|
118
|
+
id: 'my-resource-id',
|
119
|
+
name: 'My resource',
|
120
|
+
url: 'myResourceUrl',
|
121
|
+
source: {
|
122
|
+
id: 'my-source-id',
|
123
|
+
type: 'dam',
|
124
|
+
configuration: {
|
125
|
+
externalType: 'bynder',
|
126
|
+
},
|
127
|
+
},
|
128
|
+
} as unknown as ResourceBrowserResource);
|
129
|
+
|
130
|
+
render(
|
131
|
+
<ResourceBrowserSelector
|
132
|
+
modalTitle="Insert asset"
|
133
|
+
value={{ matrixIdentifier: undefined, matrixAssetId: undefined, additional: 'additional data' }}
|
134
|
+
onChange={handleChange}
|
135
|
+
/>,
|
136
|
+
);
|
137
|
+
|
138
|
+
// Trigger the onChange handler to be called
|
139
|
+
await waitFor(() => {
|
140
|
+
expect(screen.getByRole('button', { name: 'Select ResourceBrowser Resource' })).toBeInTheDocument();
|
141
|
+
});
|
142
|
+
fireEvent.click(await screen.findByRole('button', { name: 'Select ResourceBrowser Resource' }));
|
143
|
+
|
144
|
+
expect(handleChange).toHaveBeenCalledWith({
|
145
|
+
target: {
|
146
|
+
value: {
|
147
|
+
additional: 'additional data',
|
148
|
+
damObjectId: 'my-resource-id',
|
149
|
+
damSystemIdentifier: 'my-source-id',
|
150
|
+
damSystemType: 'bynder',
|
151
|
+
url: 'myResourceUrl',
|
152
|
+
nodeType: 'DAMImage',
|
153
|
+
},
|
154
|
+
},
|
155
|
+
});
|
156
|
+
});
|
157
|
+
|
158
|
+
it('ImageAsset: Calls onChange with expected value when resources is cleared', async () => {
|
159
|
+
const handleChange = jest.fn();
|
160
|
+
setSelectedResource(null);
|
161
|
+
|
162
|
+
render(
|
163
|
+
<ResourceBrowserSelector
|
164
|
+
modalTitle="Insert asset"
|
165
|
+
value={{
|
166
|
+
matrixIdentifier: 'my-source-id',
|
167
|
+
matrixAssetId: 'my-resource-id',
|
168
|
+
additional: 'additional data',
|
169
|
+
}}
|
170
|
+
onChange={handleChange}
|
171
|
+
/>,
|
172
|
+
);
|
173
|
+
|
174
|
+
// Trigger the onChange handler to be called
|
175
|
+
await waitFor(() => {
|
176
|
+
expect(screen.getByRole('button', { name: 'Select ResourceBrowser Resource' })).toBeInTheDocument();
|
177
|
+
});
|
178
|
+
fireEvent.click(await screen.findByRole('button', { name: 'Select ResourceBrowser Resource' }));
|
179
|
+
|
180
|
+
expect(handleChange).toHaveBeenCalledWith({
|
181
|
+
target: {
|
182
|
+
value: {
|
183
|
+
additional: 'additional data',
|
184
|
+
},
|
185
|
+
},
|
186
|
+
});
|
187
|
+
});
|
188
|
+
|
189
|
+
it('DAMImage: Calls onChange with expected value when resources is cleared', async () => {
|
190
|
+
const handleChange = jest.fn();
|
191
|
+
setSelectedResource(null);
|
192
|
+
|
193
|
+
render(
|
194
|
+
<ResourceBrowserSelector
|
195
|
+
modalTitle="Insert asset"
|
196
|
+
value={{
|
197
|
+
damObjectId: 'my-resource-id',
|
198
|
+
damSystemIdentifier: 'my-source-id',
|
199
|
+
additional: 'additional data',
|
200
|
+
}}
|
201
|
+
onChange={handleChange}
|
202
|
+
/>,
|
203
|
+
);
|
204
|
+
|
205
|
+
// Trigger the onChange handler to be called
|
206
|
+
await waitFor(() => {
|
207
|
+
expect(screen.getByRole('button', { name: 'Select ResourceBrowser Resource' })).toBeInTheDocument();
|
208
|
+
});
|
209
|
+
fireEvent.click(await screen.findByRole('button', { name: 'Select ResourceBrowser Resource' }));
|
210
|
+
|
211
|
+
expect(handleChange).toHaveBeenCalledWith({
|
212
|
+
target: {
|
213
|
+
value: {
|
214
|
+
additional: 'additional data',
|
215
|
+
},
|
216
|
+
},
|
217
|
+
});
|
218
|
+
});
|
219
|
+
});
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import React, { useCallback } from 'react';
|
2
|
+
import { ResourceBrowserResource, ResourceBrowser } from '@squiz/resource-browser';
|
3
|
+
import { DamResourceBrowserSource } from '@squiz/dam-resource-browser-plugin';
|
4
|
+
import { InputContainer, InputContainerProps } from '../InputContainer/InputContainer';
|
5
|
+
import { NodeName } from '../../../Extensions/Extensions';
|
6
|
+
|
7
|
+
type MatrixAsset = {
|
8
|
+
matrixIdentifier?: string;
|
9
|
+
matrixAssetId?: string;
|
10
|
+
};
|
11
|
+
type DAMAsset = {
|
12
|
+
damSystemIdentifier?: string;
|
13
|
+
damObjectId?: string;
|
14
|
+
damSystemType?: string;
|
15
|
+
};
|
16
|
+
type ResourceBrowserSelectorValue = MatrixAsset &
|
17
|
+
DAMAsset & {
|
18
|
+
nodeType?: NodeName;
|
19
|
+
url?: string;
|
20
|
+
};
|
21
|
+
|
22
|
+
export type ResourceBrowserSelectorProps<T extends ResourceBrowserSelectorValue> = Omit<
|
23
|
+
InputContainerProps,
|
24
|
+
'children'
|
25
|
+
> & {
|
26
|
+
modalTitle: string;
|
27
|
+
allowedTypes?: string[];
|
28
|
+
value?: T | null;
|
29
|
+
// LinkForm contains a "target" property.
|
30
|
+
// react-hook-form treats the presence of this property as an "Event" object being passed through, see:
|
31
|
+
// https://github.com/react-hook-form/react-hook-form/blob/master/src/logic/getEventValue.ts
|
32
|
+
// Nest the value under a "target" object to work around the behaviour.
|
33
|
+
onChange: (value: { target: { value: T } }) => void;
|
34
|
+
};
|
35
|
+
|
36
|
+
export const ResourceBrowserSelector = <T extends ResourceBrowserSelectorValue>({
|
37
|
+
modalTitle,
|
38
|
+
allowedTypes,
|
39
|
+
value,
|
40
|
+
onChange,
|
41
|
+
...props
|
42
|
+
}: ResourceBrowserSelectorProps<T>) => {
|
43
|
+
const convertFormDataToResourceBrowserValue = useCallback((value: T | null) => {
|
44
|
+
if (value?.matrixIdentifier && value?.matrixAssetId) {
|
45
|
+
return {
|
46
|
+
sourceId: value.matrixIdentifier,
|
47
|
+
resourceId: value.matrixAssetId,
|
48
|
+
};
|
49
|
+
} else if (value?.damSystemIdentifier && value?.damObjectId) {
|
50
|
+
return {
|
51
|
+
sourceId: value.damSystemIdentifier,
|
52
|
+
resourceId: value.damObjectId,
|
53
|
+
};
|
54
|
+
}
|
55
|
+
|
56
|
+
return null;
|
57
|
+
}, []);
|
58
|
+
|
59
|
+
const handleResourceChange = useCallback((resource: ResourceBrowserResource | null) => {
|
60
|
+
// Clear out any key properties for clear resource use case
|
61
|
+
let onChangeData: ResourceBrowserSelectorValue = {
|
62
|
+
...value,
|
63
|
+
matrixIdentifier: undefined,
|
64
|
+
matrixAssetId: undefined,
|
65
|
+
damSystemIdentifier: undefined,
|
66
|
+
damObjectId: undefined,
|
67
|
+
damSystemType: undefined,
|
68
|
+
url: undefined,
|
69
|
+
};
|
70
|
+
|
71
|
+
if (resource?.source?.type === 'matrix') {
|
72
|
+
onChangeData = {
|
73
|
+
...value,
|
74
|
+
matrixIdentifier: resource?.source?.id,
|
75
|
+
matrixAssetId: resource?.id,
|
76
|
+
url: resource?.url,
|
77
|
+
nodeType: NodeName.AssetImage,
|
78
|
+
};
|
79
|
+
} else if (resource?.source?.type === 'dam') {
|
80
|
+
onChangeData = {
|
81
|
+
...value,
|
82
|
+
damSystemIdentifier: resource?.source?.id,
|
83
|
+
damObjectId: resource?.id,
|
84
|
+
damSystemType: (resource?.source as DamResourceBrowserSource).configuration.externalType,
|
85
|
+
url: resource?.url,
|
86
|
+
nodeType: NodeName.DAMImage,
|
87
|
+
};
|
88
|
+
}
|
89
|
+
|
90
|
+
onChange({
|
91
|
+
target: {
|
92
|
+
value: {
|
93
|
+
...onChangeData,
|
94
|
+
} as T,
|
95
|
+
},
|
96
|
+
});
|
97
|
+
}, []);
|
98
|
+
|
99
|
+
return (
|
100
|
+
<InputContainer {...props}>
|
101
|
+
<ResourceBrowser
|
102
|
+
modalTitle={modalTitle}
|
103
|
+
allowedTypes={allowedTypes}
|
104
|
+
value={convertFormDataToResourceBrowserValue(value as T)}
|
105
|
+
onChange={handleResourceChange}
|
106
|
+
/>
|
107
|
+
</InputContainer>
|
108
|
+
);
|
109
|
+
};
|
@@ -164,6 +164,27 @@ export const sharedNodeExamples: NodeExample[] = [
|
|
164
164
|
},
|
165
165
|
],
|
166
166
|
},
|
167
|
+
{
|
168
|
+
description: 'DAM image',
|
169
|
+
remirrorNode: {
|
170
|
+
type: 'DAMImage',
|
171
|
+
attrs: {
|
172
|
+
damObjectId: '123-456-789',
|
173
|
+
damSystemIdentifier: 'zzz-xxx-ccc',
|
174
|
+
damSystemType: 'bynder',
|
175
|
+
damAdditional: JSON.stringify({ variant: 'xyz' }),
|
176
|
+
},
|
177
|
+
},
|
178
|
+
squizNode: [
|
179
|
+
{
|
180
|
+
type: 'dam-image',
|
181
|
+
damObjectId: '123-456-789',
|
182
|
+
damSystemIdentifier: 'zzz-xxx-ccc',
|
183
|
+
damSystemType: 'bynder',
|
184
|
+
damAdditional: { variant: 'xyz' },
|
185
|
+
},
|
186
|
+
],
|
187
|
+
},
|
167
188
|
];
|
168
189
|
|
169
190
|
export const squizOnlyNodeExamples: NodeExample[] = [
|
@@ -157,6 +157,16 @@ const transformNode = (node: ProsemirrorNode): FormattedNode => {
|
|
157
157
|
};
|
158
158
|
}
|
159
159
|
|
160
|
+
if (node.type.name === NodeName.DAMImage) {
|
161
|
+
transformedNode = {
|
162
|
+
type: 'dam-image',
|
163
|
+
damObjectId: node.attrs.damObjectId,
|
164
|
+
damSystemIdentifier: node.attrs.damSystemIdentifier,
|
165
|
+
damSystemType: node.attrs.damSystemType,
|
166
|
+
damAdditional: node.attrs.damAdditional ? JSON.parse(node.attrs.damAdditional) : undefined,
|
167
|
+
};
|
168
|
+
}
|
169
|
+
|
160
170
|
node.marks.forEach((mark) => {
|
161
171
|
transformedNode = transformMark(mark, transformedNode);
|
162
172
|
});
|
@@ -11,6 +11,7 @@ const getNodeType = (node: FormattedNodes): string => {
|
|
11
11
|
const typeMap: Record<string, string> = {
|
12
12
|
'link-to-matrix-asset': NodeName.Text,
|
13
13
|
'matrix-image': NodeName.AssetImage,
|
14
|
+
'dam-image': NodeName.DAMImage,
|
14
15
|
text: 'text',
|
15
16
|
};
|
16
17
|
|
@@ -95,6 +96,13 @@ const getNodeAttributes = (node: FormattedNodes): Attrs => {
|
|
95
96
|
matrixDomain: node.matrixDomain,
|
96
97
|
matrixIdentifier: node.matrixIdentifier,
|
97
98
|
};
|
99
|
+
} else if (node.type === 'dam-image') {
|
100
|
+
return {
|
101
|
+
damObjectId: node.damObjectId,
|
102
|
+
damSystemIdentifier: node.damSystemIdentifier,
|
103
|
+
damSystemType: node.damSystemType,
|
104
|
+
damAdditional: node.damAdditional ? JSON.stringify(node.damAdditional) : undefined,
|
105
|
+
};
|
98
106
|
} else if (node.type === 'tag') {
|
99
107
|
return {
|
100
108
|
nodeIndent: null,
|
package/tests/index.ts
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ResourceBrowserResource, ResourceBrowserProps } from '@squiz/resource-browser';
|
3
|
+
|
4
|
+
/*
|
5
|
+
When testing using the DAM plugin this needs to be mocked as its data fetch
|
6
|
+
logic is internal, but most of the tests in this repo were written for the Matrix plugin
|
7
|
+
which can be controlled externally.
|
8
|
+
|
9
|
+
So this is mocked in this way so the original tests can run against the actual Resource Browser
|
10
|
+
and the DAMImage tests can be run against a completely mocked one.
|
11
|
+
*/
|
12
|
+
export const mockResourceBrowser = () => {
|
13
|
+
let shouldUseMockResourceBrowser = false;
|
14
|
+
let selectedResource: ResourceBrowserResource | null = null;
|
15
|
+
const actual = jest.requireActual('@squiz/resource-browser');
|
16
|
+
|
17
|
+
return {
|
18
|
+
setSelectedResource: (value: ResourceBrowserResource | null) => {
|
19
|
+
selectedResource = value;
|
20
|
+
},
|
21
|
+
setShouldUseMockResourceBrowser: (value: boolean) => {
|
22
|
+
shouldUseMockResourceBrowser = value;
|
23
|
+
},
|
24
|
+
mockResourceBrowserImpl: (props: ResourceBrowserProps) => {
|
25
|
+
if (!shouldUseMockResourceBrowser) {
|
26
|
+
return actual.ResourceBrowser(props);
|
27
|
+
}
|
28
|
+
|
29
|
+
// This would be easier if this repo allowed 'var' statements given jest mocks don't function easily without them
|
30
|
+
return (
|
31
|
+
<div>
|
32
|
+
ResourceBrowser was rendered
|
33
|
+
<button
|
34
|
+
id="selectResource"
|
35
|
+
type="button"
|
36
|
+
onClick={() => {
|
37
|
+
props.onChange(selectedResource);
|
38
|
+
}}
|
39
|
+
>
|
40
|
+
Select ResourceBrowser Resource
|
41
|
+
</button>
|
42
|
+
</div>
|
43
|
+
);
|
44
|
+
},
|
45
|
+
};
|
46
|
+
};
|