Skip to content

Commit

Permalink
Merge pull request #258 from oleast/feat-default-tag-converter--rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
oleast authored Jan 17, 2025
2 parents 17c277c + 28fc09e commit b9491e5
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 3 deletions.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,38 @@ const converter = (node, next) => ({
});
```

Skipping an element can be done by returning the result of the `next`-function. Ignoring an element AND its' children can be done by just returning an empty array. **Skipping is the default behavior of any tag that is not supported.**
Skipping an element can be done by returning the result of the `next`-function. Ignoring an element AND its' children can be done by just returning an empty array.

```typescript
const skippingConverter = (node, next) => next(node);

const ignoringConverter = (node, next) => [];
```

### Unsupported tags

Skipping an element is the default behavior of any tag that is not supported. However, this can be overridden as follows:

```typescript
import {
htmlStringToDocument,
Options,
TagConverter,
} from "contentful-rich-text-html-parser";
import { convertTagToChildren } from "contentful-rich-text-html-parser/converters";

const logAndConvertTagToChildren: TagConverter = (node, next) => {
console.log(`Unsupported tag: ${node.tagName}`);
return convertTagToChildren(node, next); // skip element
};

const options: Options = {
defaultTagConverter: logAndConvertTagToChildren,
};

htmlStringToDocument(htmlString, options);
```

### Example: Change all "div" elements to "p" elements

```typescript
Expand Down
5 changes: 3 additions & 2 deletions src/htmlStringToDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const mapHtmlNodeToRichTextNode = (
marks: Mark[],
options: OptionsWithDefaults,
) => {
const { convertText, convertTag } = options;
const { convertText, convertTag, defaultTagConverter } = options;

const mapChildren: Next = (node, mark) => {
const newMarks = mark ? getAsList(mark) : [];
Expand All @@ -76,7 +76,7 @@ const mapHtmlNodeToRichTextNode = (
return convertText(node, marks);
}

const tagConverter = convertTag?.[node.tagName] ?? convertTagToChildren;
const tagConverter = convertTag[node.tagName] ?? defaultTagConverter;
const convertedNode = tagConverter(node, next);
return convertedNode;
};
Expand All @@ -90,6 +90,7 @@ export const htmlStringToDocument = (
...DEFAULT_TAG_CONVERTERS,
...options.convertTag,
},
defaultTagConverter: options.defaultTagConverter ?? convertTagToChildren,
convertText: options.convertText ?? convertTextNodeToText,
parserOptions: {
handleWhitespaceNodes:
Expand Down
40 changes: 40 additions & 0 deletions src/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,46 @@ describe("Parse with custom converter functions", () => {
});
});

describe("Parse unsupported tags", () => {
it("Skips element by default", () => {
const matchText = "This is text in a custom tag";
const htmlNodes = htmlStringToDocument(
`<p><custom-tag>${matchText}</custom-tag></p>`,
);

const matchNode = createDocumentNode([
helpers.createBlock(BLOCKS.PARAGRAPH, helpers.createText(matchText)),
] as TopLevelBlock[]);

expect(htmlNodes).toMatchObject(matchNode);
expect(validateRichTextDocument(htmlNodes).length).toEqual(0);
});

it("Uses default converter when specified", () => {
const toParagraphConverter: TagConverter<Block> = (node, next) => {
return {
nodeType: BLOCKS.PARAGRAPH,
content: next(node),
data: {},
};
};
const matchText = "This is text in a custom tag";
const htmlNodes = htmlStringToDocument(
`<custom-tag>${matchText}</custom-tag>`,
{
defaultTagConverter: toParagraphConverter,
},
);

const matchNode = createDocumentNode([
helpers.createBlock(BLOCKS.PARAGRAPH, helpers.createText(matchText)),
] as TopLevelBlock[]);

expect(htmlNodes).toMatchObject(matchNode);
expect(validateRichTextDocument(htmlNodes).length).toEqual(0);
});
});

describe("Processing top level inline nodes to valid formats", () => {
it("Keeps an invalid top level inline node by default", () => {
const htmlNodes = htmlStringToDocument(
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export interface PostProcessingOptions {

export interface OptionsWithDefaults {
convertTag: ConvertTagOptions;
defaultTagConverter: TagConverter;
convertText: TextConverter;
parserOptions: ParserOptions;
postProcessing: PostProcessingOptions;
Expand Down

0 comments on commit b9491e5

Please sign in to comment.