@squiz/formatted-text-editor 1.64.0 → 1.65.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/lib/Editor/Editor.d.ts +2 -2
  3. package/lib/EditorToolbar/FloatingToolbar.d.ts +2 -1
  4. package/lib/EditorToolbar/Toolbar.d.ts +2 -1
  5. package/lib/EditorToolbar/Tools/Bold/BoldButton.d.ts +2 -1
  6. package/lib/EditorToolbar/Tools/ClearFormatting/ClearFormattingButton.d.ts +2 -1
  7. package/lib/EditorToolbar/Tools/HorizontalLine/HorizontalLineButton.d.ts +2 -1
  8. package/lib/EditorToolbar/Tools/Image/ImageButton.d.ts +2 -1
  9. package/lib/EditorToolbar/Tools/Image/ImageModal.d.ts +2 -1
  10. package/lib/EditorToolbar/Tools/Italic/ItalicButton.d.ts +2 -1
  11. package/lib/EditorToolbar/Tools/Link/LinkButton.d.ts +2 -1
  12. package/lib/EditorToolbar/Tools/Link/LinkModal.d.ts +2 -1
  13. package/lib/EditorToolbar/Tools/Link/RemoveLinkButton.d.ts +2 -1
  14. package/lib/EditorToolbar/Tools/Lists/ListButtons.d.ts +2 -1
  15. package/lib/EditorToolbar/Tools/Lists/OrderedList/OrderedListButton.d.ts +2 -1
  16. package/lib/EditorToolbar/Tools/Lists/UnorderedList/UnorderedListButton.d.ts +2 -1
  17. package/lib/EditorToolbar/Tools/Redo/RedoButton.d.ts +2 -1
  18. package/lib/EditorToolbar/Tools/TextAlign/CenterAlign/CenterAlignButton.d.ts +2 -1
  19. package/lib/EditorToolbar/Tools/TextAlign/JustifyAlign/JustifyAlignButton.d.ts +2 -1
  20. package/lib/EditorToolbar/Tools/TextAlign/LeftAlign/LeftAlignButton.d.ts +2 -1
  21. package/lib/EditorToolbar/Tools/TextAlign/RightAlign/RightAlignButton.d.ts +2 -1
  22. package/lib/EditorToolbar/Tools/TextAlign/TextAlignButtons.d.ts +2 -1
  23. package/lib/EditorToolbar/Tools/TextType/CodeBlock/CodeBlockButton.d.ts +2 -1
  24. package/lib/EditorToolbar/Tools/TextType/Heading/HeadingButton.d.ts +2 -1
  25. package/lib/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.d.ts +2 -1
  26. package/lib/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.d.ts +2 -1
  27. package/lib/EditorToolbar/Tools/TextType/TextTypeDropdown.d.ts +2 -1
  28. package/lib/EditorToolbar/Tools/Underline/UnderlineButton.d.ts +2 -1
  29. package/lib/EditorToolbar/Tools/Undo/UndoButton.d.ts +2 -1
  30. package/lib/Extensions/Extensions.js +2 -0
  31. package/lib/index.d.ts +2 -1
  32. package/lib/index.js +3 -1
  33. package/lib/ui/Button/Button.d.ts +2 -2
  34. package/lib/ui/Fields/Checkbox/Checkbox.d.ts +2 -1
  35. package/lib/ui/Fields/InputContainer/InputContainer.d.ts +2 -2
  36. package/lib/ui/Fields/MatrixAsset/MatrixAsset.d.ts +2 -1
  37. package/lib/ui/Tabs/Tabs.d.ts +2 -1
  38. package/lib/ui/ToolbarDropdown/ToolbarDropdown.d.ts +2 -1
  39. package/lib/ui/ToolbarDropdownButton/ToolbarDropdownButton.d.ts +2 -1
  40. package/lib/utils/converters/htmlToSquizNode/htmlToSquizNode.d.ts +5 -0
  41. package/lib/utils/converters/htmlToSquizNode/htmlToSquizNode.js +30 -0
  42. package/lib/utils/converters/htmlToSquizNode/htmlToSquizNode.props.d.ts +3 -0
  43. package/lib/utils/converters/htmlToSquizNode/htmlToSquizNode.props.js +2 -0
  44. package/package.json +7 -3
  45. package/src/Extensions/Extensions.ts +4 -0
  46. package/src/index.ts +2 -1
  47. package/src/utils/converters/htmlToSquizNode/htmlToSquizNode.props.ts +3 -0
  48. package/src/utils/converters/htmlToSquizNode/htmlToSquizNode.spec.ts +186 -0
  49. package/src/utils/converters/htmlToSquizNode/htmlToSquizNode.ts +37 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.65.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e11f4e7: Exported function for transforming HTML to formatted text JSON.
8
+
3
9
  ## 1.64.0
4
10
 
5
11
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  import { RemirrorContentType, RemirrorEventListener, Extension } from '@remirror/core';
3
3
  type EditorProps = {
4
4
  className?: string;
@@ -11,5 +11,5 @@ type EditorProps = {
11
11
  label?: string;
12
12
  attributes?: Record<string, string>;
13
13
  };
14
- declare const Editor: ({ content, className, border, editable, onChange, children, isFocused, attributes, }: EditorProps) => JSX.Element;
14
+ declare const Editor: ({ content, className, border, editable, onChange, children, isFocused, attributes, }: EditorProps) => React.JSX.Element;
15
15
  export default Editor;
@@ -1 +1,2 @@
1
- export declare const FloatingToolbar: () => JSX.Element;
1
+ import React from 'react';
2
+ export declare const FloatingToolbar: () => React.JSX.Element;
@@ -1,5 +1,6 @@
1
+ import React from 'react';
1
2
  type ToolbarProps = {
2
3
  isVisible: boolean;
3
4
  };
4
- export declare const Toolbar: ({ isVisible }: ToolbarProps) => JSX.Element;
5
+ export declare const Toolbar: ({ isVisible }: ToolbarProps) => React.JSX.Element;
5
6
  export {};
@@ -1,2 +1,3 @@
1
- declare const BoldButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const BoldButton: () => React.JSX.Element;
2
3
  export default BoldButton;
@@ -1,2 +1,3 @@
1
- declare const ClearFormattingButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const ClearFormattingButton: () => React.JSX.Element;
2
3
  export default ClearFormattingButton;
@@ -1,2 +1,3 @@
1
- declare const HorizontalLineButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const HorizontalLineButton: () => React.JSX.Element;
2
3
  export default HorizontalLineButton;
@@ -1,5 +1,6 @@
1
+ import React from 'react';
1
2
  type ImageButtonProps = {
2
3
  inPopover?: boolean;
3
4
  };
4
- declare const ImageButton: ({ inPopover }: ImageButtonProps) => JSX.Element;
5
+ declare const ImageButton: ({ inPopover }: ImageButtonProps) => React.JSX.Element;
5
6
  export default ImageButton;
@@ -1,8 +1,9 @@
1
1
  import { ImageFormData } from './Form/ImageForm';
2
+ import React from 'react';
2
3
  import { SubmitHandler } from 'react-hook-form';
3
4
  type ImageModalProps = {
4
5
  onCancel: () => void;
5
6
  onSubmit: SubmitHandler<ImageFormData>;
6
7
  };
7
- declare const ImageModal: ({ onCancel, onSubmit }: ImageModalProps) => JSX.Element;
8
+ declare const ImageModal: ({ onCancel, onSubmit }: ImageModalProps) => React.JSX.Element;
8
9
  export default ImageModal;
@@ -1,2 +1,3 @@
1
- declare const ItalicButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const ItalicButton: () => React.JSX.Element;
2
3
  export default ItalicButton;
@@ -1,5 +1,6 @@
1
+ import React from 'react';
1
2
  export type LinkButtonProps = {
2
3
  inPopover?: boolean;
3
4
  };
4
- declare const LinkButton: ({ inPopover }: LinkButtonProps) => JSX.Element;
5
+ declare const LinkButton: ({ inPopover }: LinkButtonProps) => React.JSX.Element;
5
6
  export default LinkButton;
@@ -1,8 +1,9 @@
1
1
  import { LinkFormData } from './Form/LinkForm';
2
+ import React from 'react';
2
3
  import { SubmitHandler } from 'react-hook-form';
3
4
  type LinkModalProps = {
4
5
  onCancel: () => void;
5
6
  onSubmit: SubmitHandler<LinkFormData>;
6
7
  };
7
- declare const LinkModal: ({ onCancel, onSubmit }: LinkModalProps) => JSX.Element;
8
+ declare const LinkModal: ({ onCancel, onSubmit }: LinkModalProps) => React.JSX.Element;
8
9
  export default LinkModal;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { LinkButtonProps } from './LinkButton';
2
- declare const RemoveLinkButton: ({ inPopover }: LinkButtonProps) => JSX.Element;
3
+ declare const RemoveLinkButton: ({ inPopover }: LinkButtonProps) => React.JSX.Element;
3
4
  export default RemoveLinkButton;
@@ -1,2 +1,3 @@
1
- declare const ListButtons: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const ListButtons: () => React.JSX.Element;
2
3
  export default ListButtons;
@@ -1,2 +1,3 @@
1
- declare const OrderedListButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const OrderedListButton: () => React.JSX.Element;
2
3
  export default OrderedListButton;
@@ -1,2 +1,3 @@
1
- declare const UnorderedListButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const UnorderedListButton: () => React.JSX.Element;
2
3
  export default UnorderedListButton;
@@ -1,2 +1,3 @@
1
- declare const RedoButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const RedoButton: () => React.JSX.Element;
2
3
  export default RedoButton;
@@ -1,2 +1,3 @@
1
- declare const CenterAlignButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const CenterAlignButton: () => React.JSX.Element;
2
3
  export default CenterAlignButton;
@@ -1,2 +1,3 @@
1
- declare const JustifyAlignButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const JustifyAlignButton: () => React.JSX.Element;
2
3
  export default JustifyAlignButton;
@@ -1,2 +1,3 @@
1
- declare const LeftAlignButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const LeftAlignButton: () => React.JSX.Element;
2
3
  export default LeftAlignButton;
@@ -1,2 +1,3 @@
1
- declare const RightAlignButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const RightAlignButton: () => React.JSX.Element;
2
3
  export default RightAlignButton;
@@ -1,2 +1,3 @@
1
- declare const TextAlignButtons: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const TextAlignButtons: () => React.JSX.Element;
2
3
  export default TextAlignButtons;
@@ -1,2 +1,3 @@
1
- declare const CodeBlockButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const CodeBlockButton: () => React.JSX.Element;
2
3
  export default CodeBlockButton;
@@ -1,5 +1,6 @@
1
+ import React from 'react';
1
2
  type HeadingButtonProps = {
2
3
  level: number;
3
4
  };
4
- declare const HeadingButton: ({ level }: HeadingButtonProps) => JSX.Element;
5
+ declare const HeadingButton: ({ level }: HeadingButtonProps) => React.JSX.Element;
5
6
  export default HeadingButton;
@@ -1,2 +1,3 @@
1
- declare const ParagraphButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const ParagraphButton: () => React.JSX.Element;
2
3
  export default ParagraphButton;
@@ -1,2 +1,3 @@
1
- declare const PreformattedButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const PreformattedButton: () => React.JSX.Element;
2
3
  export default PreformattedButton;
@@ -1,2 +1,3 @@
1
- declare const TextTypeDropdown: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const TextTypeDropdown: () => React.JSX.Element;
2
3
  export default TextTypeDropdown;
@@ -1,2 +1,3 @@
1
- declare const UnderlineButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const UnderlineButton: () => React.JSX.Element;
2
3
  export default UnderlineButton;
@@ -1,2 +1,3 @@
1
- declare const UndoButton: () => JSX.Element;
1
+ import React from 'react';
2
+ declare const UndoButton: () => React.JSX.Element;
2
3
  export default UndoButton;
@@ -30,6 +30,7 @@ const createExtensions = (context, browserContext) => {
30
30
  return [
31
31
  new CommandsExtension_1.CommandsExtension(),
32
32
  new extensions_1.BoldExtension(),
33
+ new extensions_1.DocExtension(),
33
34
  new extensions_1.HeadingExtension(),
34
35
  new extensions_1.ItalicExtension(),
35
36
  new extensions_1.NodeFormattingExtension({ indents: [] }),
@@ -57,6 +58,7 @@ const createExtensions = (context, browserContext) => {
57
58
  new FetchUrlExtension_1.FetchUrlExtension({
58
59
  fetchUrl: browserContext.onRequestResource,
59
60
  }),
61
+ new extensions_1.TextExtension(),
60
62
  ];
61
63
  };
62
64
  };
package/lib/index.d.ts CHANGED
@@ -2,4 +2,5 @@ import Editor from './Editor/Editor';
2
2
  import { EditorContext } from './Editor/EditorContext';
3
3
  import { remirrorNodeToSquizNode } from './utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode';
4
4
  import { squizNodeToRemirrorNode } from './utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode';
5
- export { Editor, EditorContext, remirrorNodeToSquizNode, squizNodeToRemirrorNode };
5
+ import { htmlToSquizNode } from './utils/converters/htmlToSquizNode/htmlToSquizNode';
6
+ export { Editor, EditorContext, remirrorNodeToSquizNode, squizNodeToRemirrorNode, htmlToSquizNode };
package/lib/index.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.squizNodeToRemirrorNode = exports.remirrorNodeToSquizNode = exports.EditorContext = exports.Editor = void 0;
6
+ exports.htmlToSquizNode = exports.squizNodeToRemirrorNode = exports.remirrorNodeToSquizNode = exports.EditorContext = exports.Editor = void 0;
7
7
  const Editor_1 = __importDefault(require("./Editor/Editor"));
8
8
  exports.Editor = Editor_1.default;
9
9
  const EditorContext_1 = require("./Editor/EditorContext");
@@ -12,3 +12,5 @@ const remirrorNodeToSquizNode_1 = require("./utils/converters/remirrorNodeToSqui
12
12
  Object.defineProperty(exports, "remirrorNodeToSquizNode", { enumerable: true, get: function () { return remirrorNodeToSquizNode_1.remirrorNodeToSquizNode; } });
13
13
  const squizNodeToRemirrorNode_1 = require("./utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode");
14
14
  Object.defineProperty(exports, "squizNodeToRemirrorNode", { enumerable: true, get: function () { return squizNodeToRemirrorNode_1.squizNodeToRemirrorNode; } });
15
+ const htmlToSquizNode_1 = require("./utils/converters/htmlToSquizNode/htmlToSquizNode");
16
+ Object.defineProperty(exports, "htmlToSquizNode", { enumerable: true, get: function () { return htmlToSquizNode_1.htmlToSquizNode; } });
@@ -1,4 +1,4 @@
1
- import { ReactElement } from 'react';
1
+ import React, { ReactElement } from 'react';
2
2
  type ButtonProps = {
3
3
  handleOnClick: () => void;
4
4
  isDisabled?: boolean;
@@ -8,5 +8,5 @@ type ButtonProps = {
8
8
  icon?: ReactElement;
9
9
  className?: string;
10
10
  };
11
- declare const Button: ({ handleOnClick, isDisabled, isActive, label, text, icon, className }: ButtonProps) => JSX.Element;
11
+ declare const Button: ({ handleOnClick, isDisabled, isActive, label, text, icon, className }: ButtonProps) => React.JSX.Element;
12
12
  export default Button;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  export type CheckboxProps<TChecked, TUnchecked> = {
2
3
  label: string;
3
4
  onChange: (value: TChecked | TUnchecked) => void;
@@ -5,4 +6,4 @@ export type CheckboxProps<TChecked, TUnchecked> = {
5
6
  unchecked: TUnchecked;
6
7
  checked: TChecked;
7
8
  };
8
- export declare const Checkbox: <TChecked, TUnchecked>({ label, onChange, defaultChecked, unchecked, checked, }: CheckboxProps<TChecked, TUnchecked>) => JSX.Element;
9
+ export declare const Checkbox: <TChecked, TUnchecked>({ label, onChange, defaultChecked, unchecked, checked, }: CheckboxProps<TChecked, TUnchecked>) => React.JSX.Element;
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  export type InputContainerProps = {
3
3
  name?: string;
4
4
  label?: string;
@@ -6,4 +6,4 @@ export type InputContainerProps = {
6
6
  required?: boolean;
7
7
  children: ReactNode;
8
8
  };
9
- export declare const InputContainer: ({ name, label, error, required, children }: InputContainerProps) => JSX.Element;
9
+ export declare const InputContainer: ({ name, label, error, required, children }: InputContainerProps) => React.JSX.Element;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { InputContainerProps } from '../InputContainer/InputContainer';
2
3
  type MatrixAssetValue = {
3
4
  matrixIdentifier?: string;
@@ -14,5 +15,5 @@ export type MatrixAssetProps<T extends MatrixAssetValue> = Omit<InputContainerPr
14
15
  };
15
16
  }) => void;
16
17
  };
17
- export declare const MatrixAsset: <T extends MatrixAssetValue>({ modalTitle, allowedTypes, value, onChange, ...props }: MatrixAssetProps<T>) => JSX.Element;
18
+ export declare const MatrixAsset: <T extends MatrixAssetValue>({ modalTitle, allowedTypes, value, onChange, ...props }: MatrixAssetProps<T>) => React.JSX.Element;
18
19
  export {};
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  export type TabOptions = Record<string, TabOption>;
2
3
  export type TabOption = {
3
4
  label: string;
@@ -7,4 +8,4 @@ export type TabsProps = {
7
8
  options: TabOptions;
8
9
  onChange?: (value: string) => void;
9
10
  };
10
- export declare const Tabs: ({ value, options, onChange }: TabsProps) => JSX.Element;
11
+ export declare const Tabs: ({ value, options, onChange }: TabsProps) => React.JSX.Element;
@@ -1,6 +1,7 @@
1
+ import React from 'react';
1
2
  type ToolbarDropdownProps = {
2
3
  children: JSX.Element | JSX.Element[];
3
4
  label: string;
4
5
  };
5
- declare const ToolbarDropdown: ({ children, label }: ToolbarDropdownProps) => JSX.Element;
6
+ declare const ToolbarDropdown: ({ children, label }: ToolbarDropdownProps) => React.JSX.Element;
6
7
  export default ToolbarDropdown;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  type DropdownButtonProps = {
2
3
  children?: JSX.Element;
3
4
  handleOnClick: () => void;
@@ -6,5 +7,5 @@ type DropdownButtonProps = {
6
7
  label: string;
7
8
  icon?: JSX.Element;
8
9
  };
9
- declare const DropdownButton: ({ children, handleOnClick, isDisabled, isActive, label, icon }: DropdownButtonProps) => JSX.Element;
10
+ declare const DropdownButton: ({ children, handleOnClick, isDisabled, isActive, label, icon }: DropdownButtonProps) => React.JSX.Element;
10
11
  export default DropdownButton;
@@ -0,0 +1,5 @@
1
+ import { FORMATTED_TEXT_MODELS } from '@squiz/dx-json-schema-lib';
2
+ import { HtmlToSquizNodeProps } from './htmlToSquizNode.props';
3
+ type FormattedText = FORMATTED_TEXT_MODELS.v1.FormattedText;
4
+ export declare const htmlToSquizNode: ({ content }: HtmlToSquizNodeProps) => FormattedText | undefined;
5
+ export {};
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.htmlToSquizNode = void 0;
4
+ const remirror_1 = require("remirror");
5
+ const remirrorNodeToSquizNode_1 = require("../remirrorNodeToSquizNode/remirrorNodeToSquizNode");
6
+ const core_1 = require("@remirror/core");
7
+ const Extensions_1 = require("../../../Extensions/Extensions");
8
+ const htmlToSquizNode = ({ content }) => {
9
+ const extensions = (0, Extensions_1.createExtensions)({
10
+ matrix: {
11
+ matrixDomain: 'unsupported',
12
+ },
13
+ }, {
14
+ onRequestResource: () => {
15
+ throw new Error('Resolving Matrix assets is not supported.');
16
+ },
17
+ onRequestSources: () => {
18
+ throw new Error('Resolving Matrix assets is not supported.');
19
+ },
20
+ onRequestChildren: () => {
21
+ throw new Error('Resolving Matrix assets is not supported.');
22
+ },
23
+ });
24
+ const manager = core_1.RemirrorManager.create(extensions);
25
+ return (0, remirrorNodeToSquizNode_1.remirrorNodeToSquizNode)((0, remirror_1.htmlToProsemirrorNode)({
26
+ content,
27
+ schema: manager.schema,
28
+ }));
29
+ };
30
+ exports.htmlToSquizNode = htmlToSquizNode;
@@ -0,0 +1,3 @@
1
+ export type HtmlToSquizNodeProps = {
2
+ content: string;
3
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@squiz/formatted-text-editor",
3
- "version": "1.64.0",
3
+ "version": "1.65.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
+ "private": false,
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
6
10
  "scripts": {
7
11
  "build": "vite build",
8
12
  "clean": "rimraf ./lib tsconfig.tsbuildinfo",
@@ -32,8 +36,8 @@
32
36
  "@testing-library/react": "14.0.0",
33
37
  "@testing-library/user-event": "14.4.3",
34
38
  "@types/node": "18.15.2",
35
- "@types/react": "18.0.26",
36
- "@types/react-dom": "18.0.9",
39
+ "@types/react": "^18.2.45",
40
+ "@types/react-dom": "^18.2.18",
37
41
  "@vitejs/plugin-react": "3.0.0",
38
42
  "autoprefixer": "10.4.13",
39
43
  "cypress": "12.5.1",
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  BoldExtension,
3
+ DocExtension,
3
4
  HeadingExtension,
4
5
  ItalicExtension,
5
6
  NodeFormattingExtension,
@@ -11,6 +12,7 @@ import {
11
12
  ListItemExtension,
12
13
  PlaceholderExtension,
13
14
  HorizontalRuleExtension,
15
+ TextExtension,
14
16
  } from 'remirror/extensions';
15
17
  import { Extension } from '@remirror/core';
16
18
  import { PreformattedExtension } from './PreformattedExtension/PreformattedExtension';
@@ -43,6 +45,7 @@ export const createExtensions = (context: EditorContextOptions, browserContext:
43
45
  return [
44
46
  new CommandsExtension(),
45
47
  new BoldExtension(),
48
+ new DocExtension(),
46
49
  new HeadingExtension(),
47
50
  new ItalicExtension(),
48
51
  new NodeFormattingExtension({ indents: [] }),
@@ -70,6 +73,7 @@ export const createExtensions = (context: EditorContextOptions, browserContext:
70
73
  new FetchUrlExtension({
71
74
  fetchUrl: browserContext.onRequestResource,
72
75
  }),
76
+ new TextExtension(),
73
77
  ];
74
78
  };
75
79
  };
package/src/index.ts CHANGED
@@ -2,5 +2,6 @@ import Editor from './Editor/Editor';
2
2
  import { EditorContext } from './Editor/EditorContext';
3
3
  import { remirrorNodeToSquizNode } from './utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode';
4
4
  import { squizNodeToRemirrorNode } from './utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode';
5
+ import { htmlToSquizNode } from './utils/converters/htmlToSquizNode/htmlToSquizNode';
5
6
 
6
- export { Editor, EditorContext, remirrorNodeToSquizNode, squizNodeToRemirrorNode };
7
+ export { Editor, EditorContext, remirrorNodeToSquizNode, squizNodeToRemirrorNode, htmlToSquizNode };
@@ -0,0 +1,3 @@
1
+ export type HtmlToSquizNodeProps = {
2
+ content: string;
3
+ };
@@ -0,0 +1,186 @@
1
+ import { FORMATTED_TEXT_MODELS } from '@squiz/dx-json-schema-lib';
2
+ import { htmlToSquizNode } from './htmlToSquizNode';
3
+
4
+ type FormattedText = FORMATTED_TEXT_MODELS.v1.FormattedText;
5
+
6
+ describe('htmlToSquizNode', () => {
7
+ it.each([
8
+ ['empty string', '', undefined],
9
+ [
10
+ 'HTML with missing closing tag is converted',
11
+ '<p>Some invalid HTML content',
12
+ [
13
+ {
14
+ children: [
15
+ {
16
+ type: 'text',
17
+ value: 'Some invalid HTML content',
18
+ },
19
+ ],
20
+ tag: 'p',
21
+ type: 'tag',
22
+ },
23
+ ] as FormattedText,
24
+ ],
25
+ ['unsupported HTML is removed', '<script>var hello = "script tags are not supported";</script>', undefined],
26
+ [
27
+ 'unsupported HTML is removed, supported HTML is retained',
28
+ '<p>Paragraphs are support</p><script>var hello = "script tags are not supported";</script>' +
29
+ '<p>Another paragraph</p>',
30
+ [
31
+ {
32
+ children: [
33
+ {
34
+ type: 'text',
35
+ value: 'Paragraphs are support',
36
+ },
37
+ ],
38
+ tag: 'p',
39
+ type: 'tag',
40
+ },
41
+ {
42
+ children: [
43
+ {
44
+ type: 'text',
45
+ value: 'Another paragraph',
46
+ },
47
+ ],
48
+ tag: 'p',
49
+ type: 'tag',
50
+ },
51
+ ] as FormattedText,
52
+ ],
53
+ [
54
+ 'plain text content is nested inside a paragraph tag',
55
+ 'Plain text input',
56
+ [
57
+ {
58
+ children: [
59
+ {
60
+ type: 'text',
61
+ value: 'Plain text input',
62
+ },
63
+ ],
64
+ tag: 'p',
65
+ type: 'tag',
66
+ },
67
+ ] as FormattedText,
68
+ ],
69
+ [
70
+ 'HTML tags that are styled via classes are transformed',
71
+ '<em>Italicised text</em>, <strong>Bold text</strong>',
72
+ [
73
+ {
74
+ children: [
75
+ {
76
+ type: 'tag',
77
+ tag: 'span',
78
+ children: [
79
+ {
80
+ type: 'text',
81
+ value: 'Italicised text',
82
+ },
83
+ ],
84
+ font: {
85
+ italics: true,
86
+ },
87
+ },
88
+ {
89
+ type: 'text',
90
+ value: ', ',
91
+ },
92
+ {
93
+ type: 'tag',
94
+ tag: 'span',
95
+ children: [
96
+ {
97
+ type: 'text',
98
+ value: 'Bold text',
99
+ },
100
+ ],
101
+ font: {
102
+ bold: true,
103
+ },
104
+ },
105
+ ],
106
+ tag: 'p',
107
+ type: 'tag',
108
+ },
109
+ ] as FormattedText,
110
+ ],
111
+ [
112
+ 'HTML tags with attributes are transformed',
113
+ '<a href="https://www.google.com">Google</a>',
114
+ [
115
+ {
116
+ children: [
117
+ {
118
+ type: 'tag',
119
+ tag: 'a',
120
+ children: [
121
+ {
122
+ type: 'text',
123
+ value: 'Google',
124
+ },
125
+ ],
126
+ attributes: {
127
+ href: 'https://www.google.com',
128
+ target: '_self',
129
+ },
130
+ },
131
+ ],
132
+ tag: 'p',
133
+ type: 'tag',
134
+ },
135
+ ] as FormattedText,
136
+ ],
137
+ [
138
+ 'nested block level tags are un-nested/normalised to a supported structure',
139
+ "<div><p>Div tags are not support, <p>Nested block element also aren't</p></p>" +
140
+ '<span>Span tags are not supported</span><br />' +
141
+ 'Break lines also, you got it, not supported.',
142
+ [
143
+ {
144
+ children: [
145
+ {
146
+ type: 'text',
147
+ value: 'Div tags are not support,',
148
+ },
149
+ ],
150
+ tag: 'p',
151
+ type: 'tag',
152
+ },
153
+ {
154
+ children: [
155
+ {
156
+ type: 'text',
157
+ value: "Nested block element also aren't",
158
+ },
159
+ ],
160
+ tag: 'p',
161
+ type: 'tag',
162
+ },
163
+ {
164
+ children: [],
165
+ tag: 'p',
166
+ type: 'tag',
167
+ },
168
+ {
169
+ children: [
170
+ {
171
+ type: 'text',
172
+ value: 'Span tags are not supported Break lines also, you got it, not supported.',
173
+ },
174
+ ],
175
+ tag: 'p',
176
+ type: 'tag',
177
+ },
178
+ ] as FormattedText,
179
+ ],
180
+ ])(
181
+ 'should convert HTML to Squiz formatted text JSON - %s',
182
+ (description: string, content: string, expected: FormattedText | undefined) => {
183
+ expect(htmlToSquizNode({ content })).toEqual(expected);
184
+ },
185
+ );
186
+ });
@@ -0,0 +1,37 @@
1
+ import { htmlToProsemirrorNode } from 'remirror';
2
+ import { FORMATTED_TEXT_MODELS } from '@squiz/dx-json-schema-lib';
3
+ import { remirrorNodeToSquizNode } from '../remirrorNodeToSquizNode/remirrorNodeToSquizNode';
4
+ import { RemirrorManager } from '@remirror/core';
5
+ import { createExtensions } from '../../../Extensions/Extensions';
6
+ import { HtmlToSquizNodeProps } from './htmlToSquizNode.props';
7
+
8
+ type FormattedText = FORMATTED_TEXT_MODELS.v1.FormattedText;
9
+
10
+ export const htmlToSquizNode = ({ content }: HtmlToSquizNodeProps): FormattedText | undefined => {
11
+ const extensions = createExtensions(
12
+ {
13
+ matrix: {
14
+ matrixDomain: 'unsupported',
15
+ },
16
+ },
17
+ {
18
+ onRequestResource: () => {
19
+ throw new Error('Resolving Matrix assets is not supported.');
20
+ },
21
+ onRequestSources: () => {
22
+ throw new Error('Resolving Matrix assets is not supported.');
23
+ },
24
+ onRequestChildren: () => {
25
+ throw new Error('Resolving Matrix assets is not supported.');
26
+ },
27
+ },
28
+ );
29
+ const manager = RemirrorManager.create(extensions);
30
+
31
+ return remirrorNodeToSquizNode(
32
+ htmlToProsemirrorNode({
33
+ content,
34
+ schema: manager.schema,
35
+ }),
36
+ );
37
+ };