@squiz/formatted-text-editor 1.57.1-alpha.3 → 1.58.1-alpha.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.
@@ -8,6 +8,8 @@ type EditorProps = {
8
8
  border?: boolean;
9
9
  children?: ReactNode;
10
10
  isFocused?: boolean;
11
+ label?: string;
12
+ attributes?: Record<string, string>;
11
13
  };
12
- declare const Editor: ({ content, className, border, editable, onChange, children, isFocused }: EditorProps) => JSX.Element;
14
+ declare const Editor: ({ content, className, border, editable, onChange, children, isFocused, attributes, }: EditorProps) => JSX.Element;
13
15
  export default Editor;
@@ -47,7 +47,7 @@ const WrappedEditor = () => {
47
47
  (0, react_2.useEditorEvent)('paste', preventImagePaste);
48
48
  return react_1.default.createElement(react_2.EditorComponent, null);
49
49
  };
50
- const Editor = ({ content, className, border = true, editable = true, onChange, children, isFocused }) => {
50
+ const Editor = ({ content, className, border = true, editable = true, onChange, children, isFocused, attributes, }) => {
51
51
  const { manager, state, setState } = (0, react_2.useRemirror)({
52
52
  extensions: (0, Extensions_1.createExtensions)((0, react_1.useContext)(EditorContext_1.EditorContext), (0, react_1.useContext)(resource_browser_1.ResourceBrowserContext)),
53
53
  content,
@@ -66,7 +66,7 @@ const Editor = ({ content, className, border = true, editable = true, onChange,
66
66
  }
67
67
  }, []);
68
68
  return (react_1.default.createElement("div", { ref: wrapperRef, onBlur: handleBlur, onFocusCapture: handleFocus, className: (0, clsx_1.default)('squiz-fte-scope', 'squiz-fte-scope__editor', !editable && 'squiz-fte-scope__editor--is-disabled', border && 'squiz-fte-scope__editor--bordered', className) },
69
- react_1.default.createElement(react_2.Remirror, { manager: manager, state: state, editable: editable, onChange: handleChange, placeholder: "Write something", label: "Text editor" },
69
+ react_1.default.createElement(react_2.Remirror, { manager: manager, state: state, editable: editable, onChange: handleChange, placeholder: "Write something", label: "Text editor", attributes: attributes },
70
70
  editable && react_1.default.createElement(EditorToolbar_1.Toolbar, { isVisible: isVisible }),
71
71
  children && react_1.default.createElement("div", { className: "squiz-fte-scope__editor__children" }, children),
72
72
  react_1.default.createElement(WrappedEditor, null),
@@ -1,9 +1,11 @@
1
1
  import { ProsemirrorNode } from 'remirror';
2
2
  import { FORMATTED_TEXT_MODELS as FormattedTextModels } from '@squiz/dx-json-schema-lib';
3
+ type FormattedText = FormattedTextModels.v1.FormattedText;
3
4
  export declare const resolveNodeTag: (node: ProsemirrorNode) => string;
4
5
  /**
5
6
  * Converts Remirror node JSON structure to Squiz component JSON structure.
6
7
  * @param {ProsemirrorNode} node Remirror node to convert to component.
7
8
  * @returns {FormattedText} The converted Squiz component JSON.
8
9
  */
9
- export declare const remirrorNodeToSquizNode: (node: ProsemirrorNode) => FormattedTextModels.v1.FormattedText;
10
+ export declare const remirrorNodeToSquizNode: (node: ProsemirrorNode) => FormattedText | undefined;
11
+ export {};
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.remirrorNodeToSquizNode = exports.resolveNodeTag = void 0;
4
+ const remirror_1 = require("remirror");
4
5
  const undefinedIfEmpty_1 = require("../../undefinedIfEmpty");
5
6
  const Extensions_1 = require("../../../Extensions/Extensions");
6
7
  const resolveNodeTag = (node) => {
@@ -62,7 +63,9 @@ const transformAttributes = (attributes) => {
62
63
  };
63
64
  const transformFragment = (fragment) => {
64
65
  const transformed = [];
65
- fragment.forEach((child) => transformed.push(transformNode(child)));
66
+ fragment.forEach((child) => {
67
+ transformed.push(transformNode(child));
68
+ });
66
69
  return transformed;
67
70
  };
68
71
  const transformNode = (node) => {
@@ -178,6 +181,12 @@ const remirrorNodeToSquizNode = (node) => {
178
181
  if (node?.type?.name !== 'doc') {
179
182
  throw new Error('Unable to convert from Remirror to Node data structure, unexpected node provided.');
180
183
  }
181
- return transformFragment(node.content);
184
+ // Squiz FormattedText should be set to undefined
185
+ // To allow validation on required values
186
+ if ((0, remirror_1.isDocNodeEmpty)(node) || node.childCount === 0) {
187
+ return undefined;
188
+ }
189
+ const transformedFragment = transformFragment(node.content);
190
+ return transformedFragment;
182
191
  };
183
192
  exports.remirrorNodeToSquizNode = remirrorNodeToSquizNode;
@@ -6,4 +6,4 @@ import { FORMATTED_TEXT_MODELS as FormattedTextModels } from '@squiz/dx-json-sch
6
6
  * @export
7
7
  * @returns {RemirrorJSON} The converted Remirror JSON.
8
8
  */
9
- export declare const squizNodeToRemirrorNode: (nodes: FormattedTextModels.v1.FormattedText) => RemirrorJSON;
9
+ export declare const squizNodeToRemirrorNode: (nodes?: FormattedTextModels.v1.FormattedText) => RemirrorJSON;
@@ -143,7 +143,7 @@ const formatNode = (node) => {
143
143
  * @export
144
144
  * @returns {RemirrorJSON} The converted Remirror JSON.
145
145
  */
146
- const squizNodeToRemirrorNode = (nodes) => {
146
+ const squizNodeToRemirrorNode = (nodes = []) => {
147
147
  let children = [];
148
148
  nodes.forEach((node) => {
149
149
  try {
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@squiz/formatted-text-editor",
3
- "version": "1.57.1-alpha.3",
3
+ "version": "1.58.1-alpha.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "scripts": {
7
7
  "build": "vite build",
8
- "clean": "rimraf ./lib",
8
+ "clean": "rimraf ./lib tsconfig.tsbuildinfo",
9
9
  "compile": "npm run clean && npm run compile:styles && npm run compile:code",
10
10
  "compile:code": "tsc",
11
11
  "compile:styles": "node build.js",
@@ -19,8 +19,8 @@
19
19
  "@headlessui/react": "1.7.11",
20
20
  "@mui/icons-material": "5.11.16",
21
21
  "@remirror/react": "2.0.25",
22
- "@squiz/dx-json-schema-lib": "1.57.1-alpha.3",
23
- "@squiz/resource-browser": "1.57.1-alpha.3",
22
+ "@squiz/dx-json-schema-lib": "1.58.1-alpha.0",
23
+ "@squiz/resource-browser": "1.58.1-alpha.0",
24
24
  "clsx": "1.2.1",
25
25
  "react-hook-form": "7.43.2",
26
26
  "react-image-size": "2.0.0",
@@ -74,5 +74,5 @@
74
74
  "volta": {
75
75
  "node": "18.15.0"
76
76
  },
77
- "gitHead": "011ad01997d841dd9ab39dbb519af275d11f9dc2"
77
+ "gitHead": "e1147337893bb889e9c5d3a5e6fd0b8ab893e407"
78
78
  }
@@ -17,6 +17,8 @@ type EditorProps = {
17
17
  border?: boolean;
18
18
  children?: ReactNode;
19
19
  isFocused?: boolean;
20
+ label?: string;
21
+ attributes?: Record<string, string>;
20
22
  };
21
23
 
22
24
  const WrappedEditor = () => {
@@ -35,7 +37,16 @@ const WrappedEditor = () => {
35
37
  return <EditorComponent />;
36
38
  };
37
39
 
38
- const Editor = ({ content, className, border = true, editable = true, onChange, children, isFocused }: EditorProps) => {
40
+ const Editor = ({
41
+ content,
42
+ className,
43
+ border = true,
44
+ editable = true,
45
+ onChange,
46
+ children,
47
+ isFocused,
48
+ attributes,
49
+ }: EditorProps) => {
39
50
  const { manager, state, setState } = useRemirror({
40
51
  extensions: createExtensions(useContext(EditorContext), useContext(ResourceBrowserContext)),
41
52
  content,
@@ -77,6 +88,7 @@ const Editor = ({ content, className, border = true, editable = true, onChange,
77
88
  onChange={handleChange}
78
89
  placeholder="Write something"
79
90
  label="Text editor"
91
+ attributes={attributes}
80
92
  >
81
93
  {editable && <Toolbar isVisible={isVisible} />}
82
94
  {children && <div className="squiz-fte-scope__editor__children">{children}</div>}
@@ -457,7 +457,7 @@ describe('remirrorNodeToSquizNode', () => {
457
457
  const { editor } = await renderWithEditor(null, { content });
458
458
 
459
459
  const result = remirrorNodeToSquizNode(editor.doc);
460
- expect(result).toEqual([]);
460
+ expect(result).toBeUndefined();
461
461
  });
462
462
 
463
463
  it.each(sharedNodeExamples)(
@@ -491,6 +491,17 @@ describe('remirrorNodeToSquizNode', () => {
491
491
 
492
492
  expect(() => remirrorNodeToSquizNode(editor.doc)).toThrow('Unsupported mark "sup" was applied to node.');
493
493
  });
494
+
495
+ it('should ignore empty root node', async () => {
496
+ const { editor } = await renderWithEditor(null, {
497
+ content: {
498
+ type: 'doc',
499
+ content: [{ type: 'paragraph', content: [] }],
500
+ },
501
+ });
502
+
503
+ expect(remirrorNodeToSquizNode(editor.doc)).toBeUndefined();
504
+ });
494
505
  });
495
506
 
496
507
  describe('resolveNodeTag', () => {
@@ -1,4 +1,4 @@
1
- import { ProsemirrorNode, Fragment as ProsemirrorFragment, Mark } from 'remirror';
1
+ import { ProsemirrorNode, Fragment as ProsemirrorFragment, Mark, isDocNodeEmpty } from 'remirror';
2
2
  import { Attrs } from 'prosemirror-model';
3
3
  import { FORMATTED_TEXT_MODELS as FormattedTextModels } from '@squiz/dx-json-schema-lib';
4
4
  import { undefinedIfEmpty } from '../../undefinedIfEmpty';
@@ -90,7 +90,9 @@ const transformAttributes = (attributes: Attrs): Record<string, string> => {
90
90
  const transformFragment = (fragment: Fragment): FormattedText => {
91
91
  const transformed: FormattedText = [];
92
92
 
93
- fragment.forEach((child) => transformed.push(transformNode(child)));
93
+ fragment.forEach((child) => {
94
+ transformed.push(transformNode(child));
95
+ });
94
96
 
95
97
  return transformed;
96
98
  };
@@ -216,10 +218,17 @@ const transformMark = (mark: Mark, node: FormattedNode): FormattedNode => {
216
218
  * @param {ProsemirrorNode} node Remirror node to convert to component.
217
219
  * @returns {FormattedText} The converted Squiz component JSON.
218
220
  */
219
- export const remirrorNodeToSquizNode = (node: ProsemirrorNode): FormattedText => {
221
+ export const remirrorNodeToSquizNode = (node: ProsemirrorNode): FormattedText | undefined => {
220
222
  if (node?.type?.name !== 'doc') {
221
223
  throw new Error('Unable to convert from Remirror to Node data structure, unexpected node provided.');
222
224
  }
223
225
 
224
- return transformFragment(node.content);
226
+ // Squiz FormattedText should be set to undefined
227
+ // To allow validation on required values
228
+ if (isDocNodeEmpty(node) || node.childCount === 0) {
229
+ return undefined;
230
+ }
231
+
232
+ const transformedFragment = transformFragment(node.content);
233
+ return transformedFragment;
225
234
  };
@@ -160,7 +160,7 @@ const formatNode = (node: FormattedNodes): RemirrorJSON[] => {
160
160
  * @export
161
161
  * @returns {RemirrorJSON} The converted Remirror JSON.
162
162
  */
163
- export const squizNodeToRemirrorNode = (nodes: FormattedText): RemirrorJSON => {
163
+ export const squizNodeToRemirrorNode = (nodes: FormattedText = []): RemirrorJSON => {
164
164
  let children: RemirrorJSON[] = [];
165
165
 
166
166
  nodes.forEach((node) => {