-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add external transformers (#126)
* Adds external transformers * Rename image element fields to match original * Adds default element transformer * Adds transformer tests * exports transformers from package * Changes default transform to strip assets * Changes transforms from tuple to object with in and out props * Hanldes elements not included in the map
- Loading branch information
Showing
8 changed files
with
281 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { | ||
transformElementIn, | ||
transformElementOut, | ||
} from "../transformer/transform"; | ||
|
||
describe("transform", () => { | ||
describe("transformIn", () => { | ||
it("should not allow elements which are the wrong type", () => { | ||
// @ts-expect-error -- we should not be able to transform a malformed element | ||
transformElementIn("code", {}); | ||
|
||
transformElementIn("code", { | ||
assets: [], | ||
// @ts-expect-error -- we should not be able to transform a malformed element | ||
fields: { nonExistantField: "123" }, | ||
}); | ||
}); | ||
it("should partially transform elements with no fields", () => { | ||
const codeElement = { assets: [], fields: {} }; | ||
const result = transformElementIn("code", codeElement); | ||
|
||
expect(result).toEqual({}); | ||
}); | ||
it("should partially transform elements with some fields", () => { | ||
const codeElement = { assets: [], fields: { html: "123" } }; | ||
const result = transformElementIn("code", codeElement); | ||
|
||
expect(result).toEqual({ html: "123" }); | ||
}); | ||
it("should completely transform elements with all fields", () => { | ||
const codeElement = { | ||
assets: [], | ||
fields: { html: "123", langaue: "HTML" }, | ||
}; | ||
const result = transformElementIn("code", codeElement); | ||
|
||
expect(result).toEqual({ html: "123", langaue: "HTML" }); | ||
}); | ||
}); | ||
describe("transformOut", () => { | ||
it("should not allow elements which are the wrong type", () => { | ||
// @ts-expect-error -- we should not be able to transform a malformed element | ||
transformElementOut("code", {}); | ||
|
||
// @ts-expect-error -- we should not be able to transform a malformed element | ||
transformElementOut("code", { html: "123" }); | ||
}); | ||
it("should completely transform elements with all fields", () => { | ||
const codeElement = { html: "123", language: "HTML" }; | ||
const result = transformElementOut("code", codeElement); | ||
|
||
expect(result).toEqual({ | ||
assets: [], | ||
fields: { html: "123", language: "HTML" }, | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import type { FieldNameToValueMap } from "../../plugin/fieldViews/helpers"; | ||
import type { TransformIn, TransformOut } from "../transformer/types/Transform"; | ||
import type { Asset, createImageFields, MainImageData } from "./ImageElement"; | ||
|
||
type ImageFields = { | ||
alt: string; | ||
caption: string; | ||
displayCredit: string; | ||
imageType: string; | ||
isMandatory: string; | ||
mediaApiUri: string; | ||
mediaId: string; | ||
photographer: string; | ||
role: string; | ||
source: string; | ||
suppliersReference: string; | ||
}; | ||
|
||
type ExternalImageData = { | ||
assets: Asset[]; | ||
fields: ImageFields; | ||
}; | ||
|
||
type PartialExternalImageData = { | ||
assets: Asset[]; | ||
fields: Partial<ImageFields>; | ||
}; | ||
|
||
export const transformElementIn: TransformIn< | ||
PartialExternalImageData, | ||
ReturnType<typeof createImageFields> | ||
> = ({ assets, fields }) => { | ||
const { | ||
alt, | ||
caption, | ||
displayCredit, | ||
imageType, | ||
mediaApiUri, | ||
mediaId, | ||
photographer, | ||
role, | ||
source, | ||
suppliersReference, | ||
} = fields; | ||
|
||
const mainImage: MainImageData | undefined = { | ||
assets, | ||
suppliersReference: suppliersReference ?? "", | ||
mediaId, | ||
mediaApiUri, | ||
}; | ||
|
||
return { | ||
alt, | ||
caption, | ||
displayCredit: displayCredit === "true", | ||
imageType, | ||
photographer, | ||
role, | ||
source, | ||
mainImage, | ||
}; | ||
}; | ||
|
||
export const transformElementOut: TransformOut< | ||
ExternalImageData, | ||
ReturnType<typeof createImageFields> | ||
> = ({ | ||
alt, | ||
caption, | ||
displayCredit, | ||
imageType, | ||
photographer, | ||
role, | ||
source, | ||
mainImage, | ||
}: FieldNameToValueMap< | ||
ReturnType<typeof createImageFields> | ||
>): ExternalImageData => { | ||
return { | ||
assets: mainImage.assets, | ||
fields: { | ||
alt, | ||
caption, | ||
displayCredit: displayCredit.toString(), | ||
imageType, | ||
isMandatory: "true", | ||
mediaApiUri: mainImage.mediaApiUri ?? "", | ||
mediaId: mainImage.mediaId ?? "", | ||
photographer, | ||
role, | ||
source, | ||
suppliersReference: mainImage.suppliersReference, | ||
}, | ||
}; | ||
}; | ||
|
||
export const transformElement = { | ||
in: transformElementIn, | ||
out: transformElementOut, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import type { FieldNameToValueMap } from "../../plugin/fieldViews/helpers"; | ||
import type { FieldDescriptions } from "../../plugin/types/Element"; | ||
import type { TransformIn, TransformOut } from "./types/Transform"; | ||
|
||
type FlexibleModelElement<FDesc extends FieldDescriptions<string>> = { | ||
fields: Partial<Omit<FieldNameToValueMap<FDesc>, "assets">> & { | ||
isMandatory?: boolean; | ||
}; | ||
assets?: string[]; | ||
}; | ||
|
||
export const transformElementDataIn = < | ||
FDesc extends FieldDescriptions<string> | ||
>(): TransformIn<FlexibleModelElement<FDesc>, FDesc> => ({ fields }) => { | ||
return ({ ...fields } as unknown) as FieldNameToValueMap<FDesc>; | ||
}; | ||
|
||
export const transformElementDataOut = < | ||
FDesc extends FieldDescriptions<string> | ||
>( | ||
isMandatory?: boolean | ||
): TransformOut<FlexibleModelElement<FDesc>, FDesc> => ({ | ||
assets, | ||
...fields | ||
}: FieldNameToValueMap<FDesc>) => { | ||
const baseFields = { | ||
assets: assets || [], | ||
fields: { ...fields }, | ||
} as FlexibleModelElement<FDesc>; | ||
|
||
if (isMandatory === undefined) { | ||
return baseFields; | ||
} | ||
|
||
return { | ||
...baseFields, | ||
fields: { ...fields, isMandatory }, | ||
}; | ||
}; | ||
|
||
export const transformElement = <FDesc extends FieldDescriptions<string>>() => { | ||
return { | ||
in: transformElementDataIn<FDesc>(), | ||
out: transformElementDataOut<FDesc>(), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import type { codeFields } from "../code/CodeElementSpec"; | ||
import type { embedFields } from "../embed/EmbedSpec"; | ||
import { transformElement as imageElementTransform } from "../image/imageElementDataTransformer"; | ||
import type { pullquoteFields } from "../pullquote/PullquoteSpec"; | ||
import { transformElement as defaultElementTransform } from "./defaultTransform"; | ||
|
||
const transformMap = { | ||
code: defaultElementTransform<typeof codeFields>(), | ||
embed: defaultElementTransform<typeof embedFields>(), | ||
image: imageElementTransform, | ||
pullquote: defaultElementTransform<typeof pullquoteFields>(), | ||
} as const; | ||
|
||
type TransformMap = typeof transformMap; | ||
type TransformMapIn<Name extends keyof TransformMap> = TransformMap[Name]["in"]; | ||
type TransformMapOut< | ||
Name extends keyof TransformMap | ||
> = TransformMap[Name]["out"]; | ||
|
||
export const transformElementIn = <Name extends keyof TransformMap>( | ||
elementName: Name, | ||
values: Parameters<TransformMapIn<Name>>[0] | ||
): ReturnType<TransformMapIn<Name>> | undefined => { | ||
const transformer = transformMap[elementName]; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- This may be used in a JS context and be falst | ||
if (transformer) { | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required due to typesafety complexity between transformer and params | ||
const result = transformer.in((values as unknown) as any); | ||
return result as ReturnType<TransformMapIn<Name>>; | ||
} else { | ||
return undefined; | ||
} | ||
}; | ||
|
||
export const transformElementOut = <Name extends keyof TransformMap>( | ||
elementName: Name, | ||
values: Parameters<TransformMapOut<Name>>[0] | ||
): ReturnType<TransformMapOut<Name>> | undefined => { | ||
const transformer = transformMap[elementName]; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- This may be used in a JS context and be falst | ||
if (transformer) { | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required due to typesafety complexity between transformer and params | ||
const result = transformer.out((values as unknown) as any); | ||
return result as ReturnType<TransformMapOut<Name>>; | ||
} else { | ||
return undefined; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import type { FieldNameToValueMap } from "../../../plugin/fieldViews/helpers"; | ||
import type { FieldDescriptions } from "../../../plugin/types/Element"; | ||
|
||
export type TransformIn< | ||
ExternalData, | ||
FDesc extends FieldDescriptions<string> | ||
> = (data: ExternalData) => Partial<FieldNameToValueMap<FDesc>>; | ||
|
||
export type TransformOut< | ||
ExternalData, | ||
FDesc extends FieldDescriptions<string> | ||
> = (data: FieldNameToValueMap<FDesc>) => ExternalData; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters