Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for MAPI format #45

Merged
merged 9 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kontent-ai/rich-text-resolver",
"version": "1.0.1",
"version": "1.1.0-beta",
"private": false,
"description": "Kontent.ai rich text element resolver and PortableText transformer for JavaScript and TypeScript",
"license": "MIT",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { DomHtmlNode, DomNode, ParseResult } from "../../parser/index.js"
import {
ModularContentType,
PortableTextItem,
PortableTextLink,
PortableTextObject,
Expand Down Expand Up @@ -261,7 +262,7 @@
const imageTag = node.children[0] as DomHtmlNode;
const block = createImageBlock(uid().toString());

block.asset._ref = node.attributes['data-image-id'];
block.asset._ref = node.attributes['data-asset-id'];
block.asset.url = imageTag.attributes['src'];
block.asset.alt = imageTag.attributes['alt'];

Expand Down Expand Up @@ -291,12 +292,24 @@
};

const transformItem: TransformElementFunction = (node) => {
// data-codename reference is for DAPI, data-id for MAPI
const itemReference: Reference = {
_type: 'reference',
_ref: node.attributes['data-codename']
_ref: node.attributes['data-codename'] ?? node.attributes['data-id']

Check failure on line 298 in src/transformers/portable-text-transformer/portable-text-transformer.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary conditional, expected left-hand side of `??` operator to be possibly null or undefined
}

return [createComponentBlock(uid().toString(), itemReference)];
/**
* data-rel is only present in DAPI and acts as a differentiator
* between component and linked item in rich text
*
* data-type is present in both DAPI and MAPI but differentiates
* only in the latter
*/
const modularContentType =
(node.attributes["data-rel"] as ModularContentType) ??

Check failure on line 309 in src/transformers/portable-text-transformer/portable-text-transformer.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary conditional, expected left-hand side of `??` operator to be possibly null or undefined
(node.attributes["data-type"] as ModularContentType);

return [createComponentBlock(uid().toString(), itemReference, modularContentType)];
}

const transformLink: TransformLinkFunction = (node) => {
Expand Down
12 changes: 12 additions & 0 deletions src/transformers/transformer-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ export interface PortableTextTableCell extends ArbitraryTypedObject {
*/
export interface PortableTextComponent extends ArbitraryTypedObject {
_type: "component";
/**
* `component` for components or `item | link` for linked items
*/
dataType: ModularContentType;
/**
* Reference to a component or a linked item.
*/
Expand Down Expand Up @@ -192,6 +196,14 @@ export type PortableTextInternalObject =
*/
export type PortableTextItem = PortableTextObject | PortableTextInternalObject;

/**
* `component` represents a rich text inline component
*
* `link` and `item` represent a rich text linked item
* in delivery and management API respectively
*/
export type ModularContentType = "component" | "item" | "link";
pokornyd marked this conversation as resolved.
Show resolved Hide resolved


/**
* Re-exports all types from the package, to allow both custom types and
Expand Down
5 changes: 4 additions & 1 deletion src/utils/transformer-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ShortUniqueId from "short-unique-id";

import { DomHtmlNode, DomTextNode } from "../parser/index.js";
import {
ModularContentType,
PortableTextComponent,
PortableTextExternalLink,
PortableTextImage,
Expand Down Expand Up @@ -251,11 +252,13 @@ export const createLinkMark = (

export const createComponentBlock = (
guid: string,
reference: Reference
reference: Reference,
dataType: ModularContentType
): PortableTextComponent => {
return {
_type: "component",
_key: guid,
dataType,
component: reference,
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ exports[`portable text transformer doesn't extend link mark to adjacent spans 1`
]
`;

exports[`portable text transformer extends component with additional data 1`] = `
exports[`portable text transformer extends component block with additional data 1`] = `
[
{
"_key": "guid",
Expand All @@ -88,6 +88,7 @@ exports[`portable text transformer extends component with additional data 1`] =
"_ref": "test_item",
"_type": "reference",
},
"dataType": "link",
},
]
`;
Expand Down Expand Up @@ -274,6 +275,123 @@ exports[`portable text transformer resolves lists 1`] = `
]
`;

exports[`portable text transformer transforms a linked item and a component from DAPI with corresponding dataType 1`] = `
[
{
"_key": "guid",
"_type": "block",
"children": [
{
"_key": "guid",
"_type": "span",
"marks": [],
"text": "Some text at the first level, followed by a component. ",
},
],
"markDefs": [],
"style": "normal",
},
{
"_key": "guid",
"_type": "component",
"component": {
"_ref": "n27ec1626_93ac_0129_64e5_1beeda45416c",
"_type": "reference",
},
"dataType": "component",
},
{
"_key": "guid",
"_type": "block",
"children": [
{
"_key": "guid",
"_type": "span",
"marks": [],
"text": "and a linked item",
},
],
"markDefs": [],
"style": "normal",
},
{
"_key": "guid",
"_type": "component",
"component": {
"_ref": "commercet",
"_type": "reference",
},
"dataType": "link",
},
]
`;

exports[`portable text transformer transforms a linked item and a component from MAPI with corresponding dataType 1`] = `
[
{
"_key": "guid",
"_type": "block",
"children": [
{
"_key": "guid",
"_type": "span",
"marks": [],
"text": "Some text at the first level, followed by a component. ",
},
],
"markDefs": [],
"style": "normal",
},
{
"_key": "guid",
"_type": "component",
"component": {
"_ref": "d6a10cb4-3639-429f-b6b0-b7fea6dec252",
"_type": "reference",
},
"dataType": "component",
},
{
"_key": "guid",
"_type": "block",
"children": [
{
"_key": "guid",
"_type": "span",
"marks": [],
"text": "and a linked item",
},
],
"markDefs": [],
"style": "normal",
},
{
"_key": "guid",
"_type": "component",
"component": {
"_ref": "99e17fe7-a215-400d-813a-dc3608ee0294",
"_type": "reference",
},
"dataType": "item",
},
]
`;

exports[`portable text transformer transforms asset from MAPI 1`] = `
[
{
"_key": "guid",
"_type": "image",
"asset": {
"_ref": "62ba1f17-13e9-43c0-9530-6b44e38097fc",
"_type": "reference",
"alt": undefined,
"url": "#",
},
},
]
`;

exports[`portable text transformer transforms complex rich text into portable text 1`] = `
[
{
Expand Down Expand Up @@ -661,6 +779,7 @@ exports[`portable text transformer transforms complex rich text into portable te
"_ref": "test_item",
"_type": "reference",
},
"dataType": "link",
},
]
`;
Expand Down Expand Up @@ -809,19 +928,6 @@ exports[`portable text transformer transforms item links 1`] = `
]
`;

exports[`portable text transformer transforms linked items/components 1`] = `
[
{
"_key": "guid",
"_type": "component",
"component": {
"_ref": "test_item",
"_type": "reference",
},
},
]
`;

exports[`portable text transformer transforms lists 1`] = `
[
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,6 @@
expect(nodeResult).toMatchSnapshot();
expect(nodeResult).toMatchObject(browserResult);
})
it("transforms linked items/components", () => {
const input = `<object type="application/kenticocloud" data-type="item" data-rel="link" data-codename="test_item"></object>`;
const { nodeResult, browserResult } = transformInput(input);

expect(nodeResult).toMatchSnapshot();
expect(nodeResult).toMatchObject(browserResult);
})

it("doesn't create duplicates for nested spans", () => {
const input = `<p>text<strong>bold</strong></p>`;
Expand Down Expand Up @@ -332,7 +325,7 @@
expect(nodeResult).toMatchObject(browserResult);
})

it("extends component with additional data", () => {
it("extends component block with additional data", () => {
const input = `<object type="application/kenticocloud" data-type="item" data-rel="link" data-codename="test_item"></object>`;

const processBlock = (block: PortableTextObject) => {
Expand Down Expand Up @@ -368,4 +361,28 @@
expect(transformedResult).toMatchSnapshot();
expect(nodeResult).toMatchObject(browserResult);
})

it("transforms a linked item and a component from MAPI with corresponding dataType", () => {
const input = `<p>Some text at the first level, followed by a component.&nbsp;</p>\n<object type=\"application/kenticocloud\" data-type=\"component\" data-id=\"d6a10cb4-3639-429f-b6b0-b7fea6dec252\"></object>\n<p>and a linked item</p>\n<object type=\"application/kenticocloud\" data-type=\"item\" data-id=\"99e17fe7-a215-400d-813a-dc3608ee0294\"></object>`;

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"

Check failure on line 366 in tests/transfomers/portable-text-transformer/portable-text-transformer.spec.ts

View workflow job for this annotation

GitHub Actions / build

Unnecessary escape character: \"
pokornyd marked this conversation as resolved.
Show resolved Hide resolved
const { nodeResult, browserResult } = transformInput(input);

expect(nodeResult).toMatchSnapshot();
expect(nodeResult).toMatchObject(browserResult);
})

it("transforms asset from MAPI", () => {
const input = `<figure data-asset-id=\"62ba1f17-13e9-43c0-9530-6b44e38097fc\"><img src=\"#\" data-asset-id=\"62ba1f17-13e9-43c0-9530-6b44e38097fc\"></figure>`;
const { nodeResult, browserResult } = transformInput(input);

expect(nodeResult).toMatchSnapshot();
expect(nodeResult).toMatchObject(browserResult);
})

it("transforms a linked item and a component from DAPI with corresponding dataType", () => {
const input = `<p>Some text at the first level, followed by a component.&nbsp;</p>\n<object type=\"application/kenticocloud\" data-type=\"item\" data-rel=\"component\" data-codename=\"n27ec1626_93ac_0129_64e5_1beeda45416c\"></object>\n<p>and a linked item</p>\n<object type=\"application/kenticocloud\" data-type=\"item\" data-rel=\"link\" data-codename=\"commercet\"></object>`;
const { nodeResult, browserResult } = transformInput(input);

expect(nodeResult).toMatchSnapshot();
expect(nodeResult).toMatchObject(browserResult);
})
})
Loading