Skip to content

Commit

Permalink
wip: updated readme and unit test - turn off the lexical default norm…
Browse files Browse the repository at this point in the history
…alizer
  • Loading branch information
Sasho Mihajlov authored and Sasho Mihajlov committed Oct 10, 2023
1 parent 64d515e commit df14852
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 22 deletions.
56 changes: 38 additions & 18 deletions packages/html-to-lexical-parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,40 @@

## About

This package provides method for parsing html to lexical object.
This package provides features that will enable you to parse your HTML pages into Lexical editor state object.

Further, this lexical state object can be imported into Webiny's apps like the Page builder and Headless CMS, trough
the [Webiny's graphql API](https://www.webiny.com/docs/headless-cms/basics/graphql-api).

> Webiny use the Lexical editor as primary rich text editor across the platform.
Note: This module is built to be used in the `node.js` environment.

#### About Lexical editor

Lexical editor is product by Meta, provides rich text editing features, it's extensible and open source. In case you
are not familiar with the Lexical editor, please visit their official page
to [learn more](https://lexical.dev/docs/intro).

## Usage

To parse the html string, you need to import `parseHtmlToLexical` function, and provide
the html string.
To parse the html to lexical editor state object, you need to import `createHtmlToLexicalParser` factory function,
to create the parser function (with default or custom configuration) and provide the HTML content as parameter.
Parser will return Lexical editor state object.

> The parser uses the default configuration with the Webiny's Lexical nodes. DOM elements like headings and
> paragraph, for example, will be converted to our custom Webiny Lexical nodes.
```tsx
import {parseHtmlToLexical} from "@webiny/lexical-html-to-lexical-parser";

const htmlString = "<p>My paragraph</p>";
const lexicalObject = parseHtmlToLexical(htmlString);

// Create a parser function.
const myParser = createHtmlToLexicalParser();

// Parse the html string to Ledxical editor state object.
const lexicalEditorState = myParser(htmlString);
```

Here is the result in JSON format. This object structure is a valid Lexical editor state.
Expand Down Expand Up @@ -56,7 +78,8 @@ Here is the result in JSON format. This object structure is a valid Lexical edit
}
```

Next, you can import the parsed Lexical JSON in the Headless CMS app.
Next, you can import the parsed Lexical JSON in our Headless CMS through the Graphql API.

To find more about how to use our GraphQl API please check
our [GraphQL API Overview](https://www.webiny.com/docs/headless-cms/basics/graphql-api) article.

Expand All @@ -78,8 +101,8 @@ const addCustomThemeStyleToHeadings = (node: LexicalNode): LexicalNode => {
return node;
};

// App level configuration.
configureParser({
// Create your parser with custom configuration
const myParser = createHtmlToLexicalParser({
// Lexical editor configuration
editorConfig: {
// Add custom nodes for parsing
Expand All @@ -89,11 +112,12 @@ configureParser({
},
nodeMapper: addCustomThemeStyleToHeadings,
normalizeTextNodes: true // by default is 'true'
});

})
const lexicalEditorState = myParser(htmlString);
```

To learn more about how to create custom Lexical nodes or theme, please
To learn more about how to create custom Lexical nodes, please
visit [Lexical's documentation web page](https://lexical.dev/docs/intro).

### Configuration options
Expand All @@ -102,17 +126,13 @@ Configuration uses the `ParserConfigurationOptions` interface to define the conf

By default, this parser configuration includes all lexical nodes from the @webiny/lexical-editor package.

| Prop | Type | Default value | Description |
|--------------------|---------------------------------------------------------|---------------|----------------------------------------------------------------------|
| editorConfig | CreateEditorArgs | { nodes: [] } | Configure the Lexical editor by providing the editor initialization |
| nodeMapper | ({ node: LexicalNode, editor: LexicalEditor } => void; | | Define custom mapper function for mapping lexical nodes. |
| normalizeTextNodes | boolean | true | By default, parser will wrap single text nodes with paragraph nodes. |
| Prop | Type | Default value | Description |
|--------------------|------------------------------------------------------------|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| editorConfig | CreateEditorArgs | { nodes: [allWebinyNodes] } | Configure the Lexical editor by providing the native editor configuration options ([link to docs](https://lexical.dev/docs/api/modules/lexical#createeditorargs)) |
| nodeMapper | (node: LexicalNode, editor?: LexicalEditor) => LexicalNode | | Define custom mapper function to map the Lexical nodes. |
| normalizeTextNodes | boolean | true | By default, parser will normalize the nodes and prevent unsupported nodes to be inserted in the Lexical state. |

By providing the `editorConfig` configuration, we can add custom Lexical nodes, custom theme and other editor related
options.

Please check the full type definition, of the Lexical `CreateEditorArgs`, on the
following [link](https://lexical.dev/docs/api/modules/lexical#createeditorargs).



Expand Down
20 changes: 16 additions & 4 deletions packages/html-to-lexical-parser/__tests__/configuration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,27 @@ describe("Test how parser configuration options", () => {
it("should be able to turn off default node text node normalizer", async () => {
const parser = createHtmlToLexicalParser({ normalizeTextNodes: false });

/** By removing the default text node normalizer, text nodes can't exist alone, so we expect error to be thrown.
* Error #56 on the lexical website: https://lexical.dev/docs/error?code=56
*/
let editorState;
try {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const nodes = parser(htmlWithNotSupportedHtmlTags);
editorState = parser(htmlWithNotSupportedHtmlTags);
} catch (e) {
/** By removing the default text node normalizer, text nodes can't exist alone, so we expect error to be thrown.
* Error #56 on the lexical website: https://lexical.dev/docs/error?code=56
*/
expect(e.message).toMatch(e.message.contains("Minified Lexical error #56;"));
}

expect(editorState).toMatchObject({
root: {
children: [],
direction: null,
format: "",
indent: 0,
type: "root",
version: 1
}
});
});

it("should be able to add custom node mapper", async () => {
Expand Down

0 comments on commit df14852

Please sign in to comment.