Skip to content

Commit

Permalink
feat(api-headless-cms): expose a RichTextRenderer utility
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel910 committed May 27, 2024
1 parent 42f3b1c commit 04482b6
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CmsRichTextRendererPlugin, RTEContents } from "~/plugins";
import { CmsRichTextRendererPlugin, RichTextContents } from "~/plugins";

interface RichTextRenderer {
render(contents: RTEContents): Promise<unknown>;
render(contents: RichTextContents): Promise<unknown>;
}

class NullRenderer implements RichTextRenderer {
Expand All @@ -20,7 +20,7 @@ export class RichTextPluginsProcessor {
);
}

async render(contents: RTEContents) {
async render(contents: RichTextContents) {
return this.renderer.render(contents);
}
}
Expand All @@ -34,11 +34,11 @@ class RichTextRendererDecorator implements RichTextRenderer {
this.plugin = plugin;
}

render(contents: RTEContents) {
render(contents: RichTextContents) {
return this.plugin.render(contents, this.next);
}

private next = (contents: RTEContents) => {
private next = (contents: RichTextContents) => {
return this.renderer.render(contents);
};
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,7 @@
import { Context } from "@webiny/api/types";
import { GraphQLFieldResolver } from "@webiny/handler-graphql/types";
import { CmsModelField } from "~/types";
import { CmsRichTextRendererPlugin, RTEContents, RichTextRenderer } from "~/plugins";
import { RichTextPluginsProcessor } from "./RichTextPluginsProcessor";

const renderersMap = new Map<string, Promise<RichTextRenderer<unknown>>>();

const getRendererByType = async (format: string, context: Context) => {
if (!renderersMap.has(format)) {
const renderersFactory = new Promise<RichTextRenderer<unknown>>(resolve => {
const plugins = context.plugins
.byType<CmsRichTextRendererPlugin<unknown>>(CmsRichTextRendererPlugin.type)
.filter(plugin => plugin.format === format);

const renderer = new RichTextPluginsProcessor(plugins);

resolve((contents: RTEContents) => {
return renderer.render(contents);
});
});
renderersMap.set(format, renderersFactory);
}

return renderersMap.get(format) as Promise<RichTextRenderer<unknown>>;
};
import { CmsContext, CmsModelField } from "~/types";
import { RichTextContents } from "~/plugins";
import { RichTextRenderer } from "~/utils/RichTextRenderer";

interface ResolverArgs {
format?: string;
Expand All @@ -33,19 +11,21 @@ export const createRichTextResolver = (
field: CmsModelField
): GraphQLFieldResolver<any, ResolverArgs> => {
return async (entry, args, context) => {
const rawValue = entry[field.fieldId] as RTEContents;
const rawValue = entry[field.fieldId] as RichTextContents;
const outputFormat = args.format;

if (!outputFormat) {
return rawValue;
}

const render = await getRendererByType(outputFormat, context);
const renderer = RichTextRenderer.create(context as CmsContext);

if (field.multipleValues) {
return rawValue.map(render);
return (rawValue as RichTextContents[]).map(value =>
renderer.render(outputFormat, value)
);
}

return render(rawValue);
return renderer.render(outputFormat, rawValue);
};
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { SerializedEditorState } from "@webiny/lexical-converter";
import { CmsRichTextRendererPlugin, RTEContents } from "~/plugins";
import { CmsRichTextRendererPlugin, RichTextContents } from "~/plugins";

const isLexicalContents = (contents: RTEContents): contents is SerializedEditorState => {
const isLexicalContents = (contents: RichTextContents): contents is SerializedEditorState => {
return contents.hasOwnProperty("root");
};

Expand Down
1 change: 1 addition & 0 deletions packages/api-headless-cms/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,6 @@ export const createHeadlessCmsContext = (params: ContentContextParams) => {
export * from "~/graphqlFields";
export * from "~/plugins";
export * from "~/utils/incrementEntryIdVersion";
export * from "~/utils/RichTextRenderer";
export * from "./graphql/handleRequest";
export { entryToStorageTransform, entryFieldFromStorageTransform, entryFromStorageTransform };
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { Plugin } from "@webiny/plugins";

export interface RTEContents {
export interface RichTextContents {
[key: string]: any;
}

export interface RichTextRenderer<T> {
(contents: RTEContents): Promise<T>;
export interface CmsRichTextRenderer<T> {
(contents: RichTextContents): Promise<T>;
}

export interface RichTextRendererMiddleware<T> {
(contents: RTEContents, next: RichTextRenderer<T>): Promise<T> | T;
(contents: RichTextContents, next: CmsRichTextRenderer<T>): Promise<T> | T;
}

interface CmsRichTextRendererConstructorParams<T> {
format: string;
render: RichTextRendererMiddleware<T>;
}

export class CmsRichTextRendererPlugin<T> extends Plugin {
export class CmsRichTextRendererPlugin<T = unknown> extends Plugin {
public static override readonly type: string = "cms-rich-text-renderer";
private readonly outputFormat: string;
private readonly renderer: RichTextRendererMiddleware<T>;
Expand All @@ -32,7 +32,7 @@ export class CmsRichTextRendererPlugin<T> extends Plugin {
return this.outputFormat;
}

async render(contents: RTEContents, next: RichTextRenderer<T>) {
async render(contents: RichTextContents, next: CmsRichTextRenderer<T>) {
return this.renderer(contents, next);
}
}
Expand Down
35 changes: 35 additions & 0 deletions packages/api-headless-cms/src/utils/RichTextRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CmsRichTextRendererPlugin, RichTextContents } from "~/plugins";
import { CmsContext } from "~/types";
import { RichTextPluginsProcessor } from "~/graphqlFields/richText/RichTextPluginsProcessor";

export class RichTextRenderer {
private renderersMap = new Map<string, RichTextPluginsProcessor>();
private plugins: CmsRichTextRendererPlugin[] = [];

private constructor(plugins: CmsRichTextRendererPlugin[]) {
this.plugins = plugins;
}

static create(context: CmsContext) {
const rendererPlugins = context.plugins.byType<CmsRichTextRendererPlugin>(
CmsRichTextRendererPlugin.type
);
return new RichTextRenderer(rendererPlugins);
}

async render(format: string, contents: RichTextContents) {
const renderer = this.getRendererByType(format);

return renderer.render(contents);
}

private getRendererByType(format: string) {
if (!this.renderersMap.has(format)) {
const plugins = this.plugins.filter(plugin => plugin.format === format);

this.renderersMap.set(format, new RichTextPluginsProcessor(plugins));
}

return this.renderersMap.get(format) as RichTextPluginsProcessor;
}
}

0 comments on commit 04482b6

Please sign in to comment.