From 4006312cfce99fad734755f1db848b0f15ae64a9 Mon Sep 17 00:00:00 2001 From: Simon Emanuelsson Date: Tue, 13 Feb 2024 10:44:54 +0100 Subject: [PATCH] feat: add all default components for RTE --- components/Image/index.tsx | 10 +- components/JsonToHtml/renderOptions.tsx | 160 ++++++++++++++++++++++-- types/requests/asides/contact.ts | 2 +- 3 files changed, 159 insertions(+), 13 deletions(-) diff --git a/components/Image/index.tsx b/components/Image/index.tsx index d237a6d68..cf9b769ed 100644 --- a/components/Image/index.tsx +++ b/components/Image/index.tsx @@ -1,11 +1,17 @@ -import NextImage, { type ImageProps } from "next/image" +"use client" + +import NextImage, { type ImageProps, type ImageLoaderProps } from "next/image" + +function imageLoader({ quality, src, width }: ImageLoaderProps) { + return `${src}?w=${width}${quality ? "&q=" + quality : ""}` +} // Next/Image adds & instead of ? before the params export default function Image(props: ImageProps) { return ( ) } diff --git a/components/JsonToHtml/renderOptions.tsx b/components/JsonToHtml/renderOptions.tsx index ba6523174..0eb2a2fcc 100644 --- a/components/JsonToHtml/renderOptions.tsx +++ b/components/JsonToHtml/renderOptions.tsx @@ -7,40 +7,122 @@ import { RTEMarkType } from "@/types/rte/node" import styles from "./jsontohtml.module.css" +import type { Attributes } from "@/types/rte/attrs" import type { EmbedByUid } from "@/types/components/jsontohtml" import type { RTENext, RTEDefaultNode, RTENode, RTERegularNode } from "@/types/rte/node" import type { RenderOptions } from "@/types/rte/option" +function extractPossibleAttributes(attrs: Attributes) { + const props: Record = {} + if (attrs.id) { + props.id = attrs.id + } + + if (attrs.class) { + props.className = attrs.class + } else if (attrs["class-name"]) { + props.className = attrs["class-name"] + } else if (attrs.classname) { + props.className = attrs.classname + } + + return props +} + export const renderOptions: RenderOptions = { [RTETypeEnum.a]: (node: RTERegularNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { if (node.attrs.url) { + const props = extractPossibleAttributes(node.attrs) return ( - {next(node.children, embeds, fullRenderOptions)} + + {next(node.children, embeds, fullRenderOptions)} + ) } return null }, + + [RTETypeEnum.blockquote]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return
{next(node.children, embeds, fullRenderOptions)}
+ }, + + [RTETypeEnum.code]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)} + }, + + [RTETypeEnum.embed]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + if (node.attrs.src) { + props.src = node.attrs.src + } + if (node.attrs.url) { + props.src = node.attrs.url + } + if (!props.src) { + return null + } + return ( + + ) + }, + [RTETypeEnum.h1]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { - return

{next(node.children, embeds, fullRenderOptions)}

+ const props = extractPossibleAttributes(node.attrs) + return

{next(node.children, embeds, fullRenderOptions)}

}, + [RTETypeEnum.h2]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { - return

{next(node.children, embeds, fullRenderOptions)}

+ const props = extractPossibleAttributes(node.attrs) + return

{next(node.children, embeds, fullRenderOptions)}

}, + [RTETypeEnum.h3]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { - return

{next(node.children, embeds, fullRenderOptions)}

+ const props = extractPossibleAttributes(node.attrs) + return

{next(node.children, embeds, fullRenderOptions)}

}, + [RTETypeEnum.h4]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { - return

{next(node.children, embeds, fullRenderOptions)}

+ const props = extractPossibleAttributes(node.attrs) + return

{next(node.children, embeds, fullRenderOptions)}

}, + [RTETypeEnum.h5]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { - return
{next(node.children, embeds, fullRenderOptions)}
+ const props = extractPossibleAttributes(node.attrs) + return
{next(node.children, embeds, fullRenderOptions)}
}, + [RTETypeEnum.h6]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { - return
{next(node.children, embeds, fullRenderOptions)}
+ const props = extractPossibleAttributes(node.attrs) + return
{next(node.children, embeds, fullRenderOptions)}
}, + + [RTETypeEnum.hr]: () => { + return
+ }, + + [RTETypeEnum.li]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return
  • {next(node.children, embeds, fullRenderOptions)}
  • + }, + + [RTETypeEnum.ol]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return
      {next(node.children, embeds, fullRenderOptions)}
    + }, + [RTETypeEnum.p]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { - return

    {next(node.children, embeds, fullRenderOptions)}

    + const props = extractPossibleAttributes(node.attrs) + return

    {next(node.children, embeds, fullRenderOptions)}

    }, + [RTETypeEnum.reference]: (node: RTENode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { if ("attrs" in node) { const type = node.attrs.type @@ -59,8 +141,9 @@ export const renderOptions: RenderOptions = { ) } } else { + const props = extractPossibleAttributes(node.attrs) return ( - + {next(node.children, embeds, fullRenderOptions)} ) @@ -70,27 +153,75 @@ export const renderOptions: RenderOptions = { return null }, + [RTETypeEnum.table]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)}
    + }, + + [RTETypeEnum.thead]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)} + }, + + [RTETypeEnum.tbody]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)} + }, + + [RTETypeEnum.tfoot]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)} + }, + + [RTETypeEnum.tr]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)} + }, + + [RTETypeEnum.th]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)} + }, + + [RTETypeEnum.td]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return {next(node.children, embeds, fullRenderOptions)} + }, + + [RTETypeEnum.ul]: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + const props = extractPossibleAttributes(node.attrs) + return
      {next(node.children, embeds, fullRenderOptions)}
    + }, + + /** TextNode wrappers */ [RTEMarkType.bold]: (children: React.ReactNode) => { return {children} }, + [RTEMarkType.italic]: (children: React.ReactNode) => { return {children} }, + [RTEMarkType.underline]: (children: React.ReactNode) => { return {children} }, + [RTEMarkType.strikethrough]: (children: React.ReactNode) => { return {children} }, + [RTEMarkType.inlineCode]: (children: React.ReactNode) => { return {children} }, + [RTEMarkType.subscript]: (children: React.ReactNode) => { return {children} }, + [RTEMarkType.superscript]: (children: React.ReactNode) => { return {children} }, + [RTEMarkType.break]: (children: React.ReactNode) => { return ( <> @@ -99,6 +230,7 @@ export const renderOptions: RenderOptions = { ) }, + [RTEMarkType.classnameOrId]: (children: React.ReactNode, className?: string, id?: string) => { let props = { className, @@ -111,5 +243,13 @@ export const renderOptions: RenderOptions = { delete props.id } return {children} - } + }, + + /** + * Contentstack can return something called `default` as seen here in their + * own SDK (https://github.com/contentstack/contentstack-utils-javascript/blob/master/src/options/default-node-options.ts#L89) + */ + default: (node: RTEDefaultNode, embeds: EmbedByUid, next: RTENext, fullRenderOptions: RenderOptions) => { + return next(node.children, embeds, fullRenderOptions) + }, } diff --git a/types/requests/asides/contact.ts b/types/requests/asides/contact.ts index 268993fd4..af9e1ada0 100644 --- a/types/requests/asides/contact.ts +++ b/types/requests/asides/contact.ts @@ -1,5 +1,5 @@ -import { Lang } from "@/types/lang" import type { Edges } from "../utils/edges" +import type { Lang } from "@/types/lang" export type ContactNode = { mailing_address: {