@squiz/formatted-text-editor 1.66.3 → 1.67.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 +14 -0
- package/lib/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.js +30 -20
- package/lib/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.js +8 -0
- package/package.json +2 -2
- package/src/utils/converters/htmlToSquizNode/htmlToSquizNode.spec.ts +2 -8
- package/src/utils/converters/mocks/squizNodeJson.mock.ts +8 -9
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.spec.ts +30 -22
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.ts +50 -22
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.ts +6 -0
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 1.67.0
|
4
|
+
|
5
|
+
### Minor Changes
|
6
|
+
|
7
|
+
- 6867717: Changed output of FTE to use semantic HTML where applicable
|
8
|
+
|
9
|
+
## 1.66.4
|
10
|
+
|
11
|
+
### Patch Changes
|
12
|
+
|
13
|
+
- 8421756: Selected image assets in the resource browser will now display the actual image instead of just the image asset icon if they have a URL specified
|
14
|
+
- Updated dependencies [8421756]
|
15
|
+
- @squiz/resource-browser@1.66.3
|
16
|
+
|
3
17
|
## 1.66.3
|
4
18
|
|
5
19
|
### Patch Changes
|
@@ -48,12 +48,6 @@ const resolveFontOptions = (node) => {
|
|
48
48
|
const fontOptions = {};
|
49
49
|
node.marks.forEach((mark) => {
|
50
50
|
switch (mark.type.name) {
|
51
|
-
case 'bold':
|
52
|
-
fontOptions.bold = true;
|
53
|
-
break;
|
54
|
-
case 'italic':
|
55
|
-
fontOptions.italics = true;
|
56
|
-
break;
|
57
51
|
case 'underline':
|
58
52
|
fontOptions.underline = true;
|
59
53
|
break;
|
@@ -109,14 +103,7 @@ const transformNode = (node) => {
|
|
109
103
|
};
|
110
104
|
}
|
111
105
|
node.marks.forEach((mark) => {
|
112
|
-
|
113
|
-
case 'bold':
|
114
|
-
case 'italic':
|
115
|
-
case 'underline':
|
116
|
-
break;
|
117
|
-
default:
|
118
|
-
transformedNode = transformMark(mark, transformedNode);
|
119
|
-
}
|
106
|
+
transformedNode = transformMark(mark, transformedNode);
|
120
107
|
});
|
121
108
|
if (node.type.name === Extensions_1.NodeName.Unsupported) {
|
122
109
|
const unsupportedNode = node.attrs?.originalNode;
|
@@ -133,7 +120,7 @@ const transformNode = (node) => {
|
|
133
120
|
*
|
134
121
|
* @return {FormattedNode}
|
135
122
|
*/
|
136
|
-
const wrapNodeIfNeeded = (node, wrappingNode) => {
|
123
|
+
const wrapNodeIfNeeded = (node, wrappingNode, copyFont = true) => {
|
137
124
|
if (node.type === 'tag' && wrappingNode.type === 'tag' && (node.tag === 'span' || node.tag === wrappingNode.tag)) {
|
138
125
|
// if the node we are wrapping with is a DOM node, and the node being wrapped is
|
139
126
|
// a plain looking DOM node merge the 2 nodes.
|
@@ -148,10 +135,12 @@ const wrapNodeIfNeeded = (node, wrappingNode) => {
|
|
148
135
|
...node.attributes,
|
149
136
|
...wrappingNode.attributes,
|
150
137
|
}),
|
151
|
-
font: (0, undefinedIfEmpty_1.undefinedIfEmpty)(
|
152
|
-
|
153
|
-
|
154
|
-
|
138
|
+
font: (0, undefinedIfEmpty_1.undefinedIfEmpty)(copyFont
|
139
|
+
? {
|
140
|
+
...node.font,
|
141
|
+
...wrappingNode.font,
|
142
|
+
}
|
143
|
+
: {}),
|
155
144
|
children: [...node.children, ...wrappingNode.children],
|
156
145
|
};
|
157
146
|
}
|
@@ -163,13 +152,34 @@ const wrapNodeIfNeeded = (node, wrappingNode) => {
|
|
163
152
|
};
|
164
153
|
const transformMark = (mark, node) => {
|
165
154
|
switch (mark.type.name) {
|
155
|
+
case 'bold':
|
156
|
+
return wrapNodeIfNeeded(node, {
|
157
|
+
type: 'tag',
|
158
|
+
tag: 'strong',
|
159
|
+
children: [],
|
160
|
+
}, false);
|
161
|
+
case 'italic':
|
162
|
+
return wrapNodeIfNeeded(node, {
|
163
|
+
type: 'tag',
|
164
|
+
tag: 'em',
|
165
|
+
children: [],
|
166
|
+
}, false);
|
167
|
+
case 'underline':
|
168
|
+
return wrapNodeIfNeeded(node, {
|
169
|
+
type: 'tag',
|
170
|
+
tag: 'span',
|
171
|
+
children: [],
|
172
|
+
font: {
|
173
|
+
underline: mark.type.name === 'underline',
|
174
|
+
},
|
175
|
+
});
|
166
176
|
case 'link':
|
167
177
|
return wrapNodeIfNeeded(node, {
|
168
178
|
type: 'tag',
|
169
179
|
tag: 'a',
|
170
180
|
attributes: transformAttributes(mark.attrs),
|
171
181
|
children: [],
|
172
|
-
});
|
182
|
+
}, false);
|
173
183
|
case 'assetLink':
|
174
184
|
return wrapNodeIfNeeded(node, {
|
175
185
|
type: 'link-to-matrix-asset',
|
@@ -24,7 +24,9 @@ const getNodeType = (node) => {
|
|
24
24
|
ul: 'bulletList',
|
25
25
|
hr: 'horizontalRule',
|
26
26
|
a: Extensions_1.NodeName.Text,
|
27
|
+
em: Extensions_1.NodeName.Text,
|
27
28
|
span: Extensions_1.NodeName.Text,
|
29
|
+
strong: Extensions_1.NodeName.Text,
|
28
30
|
code: Extensions_1.NodeName.CodeBlock,
|
29
31
|
};
|
30
32
|
if (typeMap[node.type]) {
|
@@ -96,6 +98,12 @@ const getNodeMarks = (node) => {
|
|
96
98
|
},
|
97
99
|
});
|
98
100
|
}
|
101
|
+
else if (node.type === 'tag' && node.tag === 'strong') {
|
102
|
+
marks.push({ type: 'bold' });
|
103
|
+
}
|
104
|
+
else if (node.type === 'tag' && node.tag === 'em') {
|
105
|
+
marks.push({ type: 'italic' });
|
106
|
+
}
|
99
107
|
// Handle font formatting
|
100
108
|
if ('font' in node && node.font !== undefined) {
|
101
109
|
for (const [type, enabled] of Object.entries(node.font)) {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/formatted-text-editor",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.67.0",
|
4
4
|
"main": "lib/index.js",
|
5
5
|
"types": "lib/index.d.ts",
|
6
6
|
"private": false,
|
@@ -24,7 +24,7 @@
|
|
24
24
|
"@mui/icons-material": "5.11.16",
|
25
25
|
"@remirror/react": "2.0.25",
|
26
26
|
"@squiz/dx-json-schema-lib": "^1.65.0",
|
27
|
-
"@squiz/resource-browser": "^1.
|
27
|
+
"@squiz/resource-browser": "^1.66.3",
|
28
28
|
"clsx": "1.2.1",
|
29
29
|
"react-hook-form": "7.43.2",
|
30
30
|
"react-image-size": "2.0.0",
|
@@ -74,16 +74,13 @@ describe('htmlToSquizNode', () => {
|
|
74
74
|
children: [
|
75
75
|
{
|
76
76
|
type: 'tag',
|
77
|
-
tag: '
|
77
|
+
tag: 'em',
|
78
78
|
children: [
|
79
79
|
{
|
80
80
|
type: 'text',
|
81
81
|
value: 'Italicised text',
|
82
82
|
},
|
83
83
|
],
|
84
|
-
font: {
|
85
|
-
italics: true,
|
86
|
-
},
|
87
84
|
},
|
88
85
|
{
|
89
86
|
type: 'text',
|
@@ -91,16 +88,13 @@ describe('htmlToSquizNode', () => {
|
|
91
88
|
},
|
92
89
|
{
|
93
90
|
type: 'tag',
|
94
|
-
tag: '
|
91
|
+
tag: 'strong',
|
95
92
|
children: [
|
96
93
|
{
|
97
94
|
type: 'text',
|
98
95
|
value: 'Bold text',
|
99
96
|
},
|
100
97
|
],
|
101
|
-
font: {
|
102
|
-
bold: true,
|
103
|
-
},
|
104
98
|
},
|
105
99
|
],
|
106
100
|
tag: 'p',
|
@@ -116,7 +116,6 @@ export const sharedNodeExamples: NodeExample[] = [
|
|
116
116
|
type: 'text',
|
117
117
|
text: 'Hello',
|
118
118
|
marks: [
|
119
|
-
{ type: 'bold' },
|
120
119
|
{
|
121
120
|
type: 'assetLink',
|
122
121
|
attrs: {
|
@@ -126,20 +125,20 @@ export const sharedNodeExamples: NodeExample[] = [
|
|
126
125
|
matrixIdentifier: 'matrix-api-identifier',
|
127
126
|
},
|
128
127
|
},
|
128
|
+
{ type: 'bold' },
|
129
129
|
],
|
130
130
|
},
|
131
131
|
squizNode: [
|
132
132
|
{
|
133
|
-
type: '
|
134
|
-
|
135
|
-
matrixAssetId: '123',
|
136
|
-
matrixDomain: 'https://my-matrix.squiz.net',
|
137
|
-
matrixIdentifier: 'matrix-api-identifier',
|
133
|
+
type: 'tag',
|
134
|
+
tag: 'strong',
|
138
135
|
children: [
|
139
136
|
{
|
140
|
-
type: '
|
141
|
-
|
142
|
-
|
137
|
+
type: 'link-to-matrix-asset',
|
138
|
+
target: '_blank',
|
139
|
+
matrixAssetId: '123',
|
140
|
+
matrixDomain: 'https://my-matrix.squiz.net',
|
141
|
+
matrixIdentifier: 'matrix-api-identifier',
|
143
142
|
children: [{ type: 'text', value: 'Hello' }],
|
144
143
|
},
|
145
144
|
],
|
@@ -329,10 +329,7 @@ describe('remirrorNodeToSquizNode', () => {
|
|
329
329
|
value: ' click',
|
330
330
|
},
|
331
331
|
],
|
332
|
-
|
333
|
-
bold: true,
|
334
|
-
},
|
335
|
-
tag: 'span',
|
332
|
+
tag: 'strong',
|
336
333
|
type: 'tag',
|
337
334
|
},
|
338
335
|
{
|
@@ -342,18 +339,22 @@ describe('remirrorNodeToSquizNode', () => {
|
|
342
339
|
{
|
343
340
|
children: [
|
344
341
|
{
|
345
|
-
type: '
|
346
|
-
|
342
|
+
type: 'tag',
|
343
|
+
tag: 'a',
|
344
|
+
children: [
|
345
|
+
{
|
346
|
+
type: 'text',
|
347
|
+
value: 'here',
|
348
|
+
},
|
349
|
+
],
|
350
|
+
attributes: {
|
351
|
+
href: 'https://www.google.com/',
|
352
|
+
title: '',
|
353
|
+
},
|
347
354
|
},
|
348
355
|
],
|
349
|
-
|
350
|
-
|
351
|
-
title: '',
|
352
|
-
},
|
353
|
-
font: {
|
354
|
-
italics: true,
|
355
|
-
},
|
356
|
-
tag: 'a',
|
356
|
+
|
357
|
+
tag: 'em',
|
357
358
|
type: 'tag',
|
358
359
|
},
|
359
360
|
{
|
@@ -363,10 +364,7 @@ describe('remirrorNodeToSquizNode', () => {
|
|
363
364
|
value: ' ',
|
364
365
|
},
|
365
366
|
],
|
366
|
-
|
367
|
-
italics: true,
|
368
|
-
},
|
369
|
-
tag: 'span',
|
367
|
+
tag: 'em',
|
370
368
|
type: 'tag',
|
371
369
|
},
|
372
370
|
{
|
@@ -376,13 +374,23 @@ describe('remirrorNodeToSquizNode', () => {
|
|
376
374
|
{
|
377
375
|
children: [
|
378
376
|
{
|
379
|
-
type: '
|
380
|
-
|
377
|
+
type: 'tag',
|
378
|
+
tag: 'em',
|
379
|
+
children: [
|
380
|
+
{
|
381
|
+
type: 'tag',
|
382
|
+
tag: 'strong',
|
383
|
+
children: [
|
384
|
+
{
|
385
|
+
type: 'text',
|
386
|
+
value: ' GOOGLE!',
|
387
|
+
},
|
388
|
+
],
|
389
|
+
},
|
390
|
+
],
|
381
391
|
},
|
382
392
|
],
|
383
393
|
font: {
|
384
|
-
bold: true,
|
385
|
-
italics: true,
|
386
394
|
underline: true,
|
387
395
|
},
|
388
396
|
tag: 'span',
|
@@ -71,12 +71,6 @@ const resolveFontOptions = (node: ProsemirrorNode): FormattedNodeFontProperties
|
|
71
71
|
|
72
72
|
node.marks.forEach((mark) => {
|
73
73
|
switch (mark.type.name) {
|
74
|
-
case 'bold':
|
75
|
-
fontOptions.bold = true;
|
76
|
-
break;
|
77
|
-
case 'italic':
|
78
|
-
fontOptions.italics = true;
|
79
|
-
break;
|
80
74
|
case 'underline':
|
81
75
|
fontOptions.underline = true;
|
82
76
|
break;
|
@@ -145,14 +139,7 @@ const transformNode = (node: ProsemirrorNode): FormattedNode => {
|
|
145
139
|
}
|
146
140
|
|
147
141
|
node.marks.forEach((mark) => {
|
148
|
-
|
149
|
-
case 'bold':
|
150
|
-
case 'italic':
|
151
|
-
case 'underline':
|
152
|
-
break;
|
153
|
-
default:
|
154
|
-
transformedNode = transformMark(mark, transformedNode);
|
155
|
-
}
|
142
|
+
transformedNode = transformMark(mark, transformedNode);
|
156
143
|
});
|
157
144
|
|
158
145
|
if (node.type.name === NodeName.Unsupported) {
|
@@ -172,7 +159,11 @@ const transformNode = (node: ProsemirrorNode): FormattedNode => {
|
|
172
159
|
*
|
173
160
|
* @return {FormattedNode}
|
174
161
|
*/
|
175
|
-
const wrapNodeIfNeeded = (
|
162
|
+
const wrapNodeIfNeeded = (
|
163
|
+
node: FormattedNode,
|
164
|
+
wrappingNode: FormattedNodeWithChildren,
|
165
|
+
copyFont: boolean = true,
|
166
|
+
): FormattedNode => {
|
176
167
|
if (node.type === 'tag' && wrappingNode.type === 'tag' && (node.tag === 'span' || node.tag === wrappingNode.tag)) {
|
177
168
|
// if the node we are wrapping with is a DOM node, and the node being wrapped is
|
178
169
|
// a plain looking DOM node merge the 2 nodes.
|
@@ -187,10 +178,14 @@ const wrapNodeIfNeeded = (node: FormattedNode, wrappingNode: FormattedNodeWithCh
|
|
187
178
|
...node.attributes,
|
188
179
|
...wrappingNode.attributes,
|
189
180
|
}),
|
190
|
-
font: undefinedIfEmpty(
|
191
|
-
|
192
|
-
|
193
|
-
|
181
|
+
font: undefinedIfEmpty(
|
182
|
+
copyFont
|
183
|
+
? {
|
184
|
+
...node.font,
|
185
|
+
...wrappingNode.font,
|
186
|
+
}
|
187
|
+
: {},
|
188
|
+
),
|
194
189
|
children: [...node.children, ...wrappingNode.children],
|
195
190
|
};
|
196
191
|
}
|
@@ -204,13 +199,46 @@ const wrapNodeIfNeeded = (node: FormattedNode, wrappingNode: FormattedNodeWithCh
|
|
204
199
|
|
205
200
|
const transformMark = (mark: Mark, node: FormattedNode): FormattedNode => {
|
206
201
|
switch (mark.type.name) {
|
207
|
-
case '
|
202
|
+
case 'bold':
|
203
|
+
return wrapNodeIfNeeded(
|
204
|
+
node,
|
205
|
+
{
|
206
|
+
type: 'tag',
|
207
|
+
tag: 'strong',
|
208
|
+
children: [],
|
209
|
+
},
|
210
|
+
false,
|
211
|
+
);
|
212
|
+
case 'italic':
|
213
|
+
return wrapNodeIfNeeded(
|
214
|
+
node,
|
215
|
+
{
|
216
|
+
type: 'tag',
|
217
|
+
tag: 'em',
|
218
|
+
children: [],
|
219
|
+
},
|
220
|
+
false,
|
221
|
+
);
|
222
|
+
case 'underline':
|
208
223
|
return wrapNodeIfNeeded(node, {
|
209
224
|
type: 'tag',
|
210
|
-
tag: '
|
211
|
-
attributes: transformAttributes(mark.attrs),
|
225
|
+
tag: 'span',
|
212
226
|
children: [],
|
227
|
+
font: {
|
228
|
+
underline: mark.type.name === 'underline',
|
229
|
+
},
|
213
230
|
});
|
231
|
+
case 'link':
|
232
|
+
return wrapNodeIfNeeded(
|
233
|
+
node,
|
234
|
+
{
|
235
|
+
type: 'tag',
|
236
|
+
tag: 'a',
|
237
|
+
attributes: transformAttributes(mark.attrs),
|
238
|
+
children: [],
|
239
|
+
},
|
240
|
+
false,
|
241
|
+
);
|
214
242
|
case 'assetLink':
|
215
243
|
return wrapNodeIfNeeded(node, {
|
216
244
|
type: 'link-to-matrix-asset',
|
@@ -29,7 +29,9 @@ const getNodeType = (node: FormattedNodes): string => {
|
|
29
29
|
ul: 'bulletList',
|
30
30
|
hr: 'horizontalRule',
|
31
31
|
a: NodeName.Text,
|
32
|
+
em: NodeName.Text,
|
32
33
|
span: NodeName.Text,
|
34
|
+
strong: NodeName.Text,
|
33
35
|
code: NodeName.CodeBlock,
|
34
36
|
};
|
35
37
|
|
@@ -105,6 +107,10 @@ const getNodeMarks = (node: FormattedNodes): ObjectMark[] => {
|
|
105
107
|
target: node.target,
|
106
108
|
},
|
107
109
|
});
|
110
|
+
} else if (node.type === 'tag' && node.tag === 'strong') {
|
111
|
+
marks.push({ type: 'bold' });
|
112
|
+
} else if (node.type === 'tag' && node.tag === 'em') {
|
113
|
+
marks.push({ type: 'italic' });
|
108
114
|
}
|
109
115
|
|
110
116
|
// Handle font formatting
|