Renamed inlineComponents to richTextComponents as this is closer to what they are

This commit was merged in pull request #16.
This commit is contained in:
2023-09-19 17:22:14 +02:00
parent 6be84ae480
commit 6f3e84de94
8 changed files with 8 additions and 8 deletions

View File

@@ -0,0 +1,35 @@
import { TinaMarkdown, TinaMarkdownContent } from "tinacms/dist/rich-text";
import { RichTextTemplate } from "@tinacms/schema-tools";
import React from "react";
export interface BlockQuoteProps {
children: TinaMarkdownContent;
authorName: string;
}
const BlockQuote = (props: BlockQuoteProps): React.ReactElement => (
<div>
<blockquote>
<TinaMarkdown content={ props.children } />
{ props.authorName }
</blockquote>
</div>);
export const blockQuoteSchema: RichTextTemplate = {
name: "BlockQuote",
label: "Block Quote",
fields: [
{
name: "children",
label: "Quote",
type: "rich-text"
},
{
name: "authorName",
label: "Author",
type: "string"
}
]
};
export default BlockQuote;

View File

@@ -0,0 +1,39 @@
import React from "react";
import format from "date-fns/format";
import { RichTextTemplate } from "@tinacms/schema-tools";
export interface DateTimeProps {
format?: string;
}
const DateTime = (props: DateTimeProps) => {
const dt = React.useMemo(() => {
return new Date();
}, []);
switch (props.format) {
case "iso":
return <span>{ format(dt, "yyyy-MM-dd") }</span>;
case "utc":
return <span>{ format(dt, "eee, dd MMM yyyy HH:mm:ss OOOO") }</span>;
case "local":
return <span>{ format(dt, "P") }</span>;
default:
return <span>{ format(dt, "P") }</span>;
}
};
export const dateTimeSchema: RichTextTemplate = {
name: "DateTime",
label: "Date & Time",
inline: true,
fields: [
{
name: "format",
label: "Format",
type: "string",
options: ["utc", "iso", "local"]
}
] };
export default DateTime;

View File

@@ -0,0 +1,135 @@
import { TinaMarkdownContent } from "tinacms/dist/rich-text";
import { RichTextTemplate } from "@tinacms/schema-tools";
import { tinaField } from "tinacms/dist/react";
enum imageSize {
extraSmall = "extra-small",
small = "small",
medium = "medium",
large = "large"
}
enum imageDecorations {
default = "default",
noStyle = "no-style"
}
enum imagePosition {
left = "left",
middle = "middle",
right = "right"
}
export interface ImageProps {
children: TinaMarkdownContent;
size: imageSize;
imageUrl: string,
decorations: imageDecorations,
position: imagePosition,
inline: boolean,
alt: string
}
const Image = (props: ImageProps) => {
const getDecorationTypeClass = (): string | undefined => {
switch (props.decorations) {
case imageDecorations.default:
return "default-border";
case imageDecorations.noStyle:
return undefined;
default:
return undefined;
}
};
const getSizeTypeClass = (): string | undefined => {
switch (props.size) {
case imageSize.extraSmall:
return "xs-size";
case imageSize.small:
return "sm-size";
case imageSize.medium:
return "md-size";
case imageSize.large:
return "lg-size";
default:
return undefined;
}
};
const getPositionTypeClass = (): string | undefined => {
switch (props.position) {
case imagePosition.left:
return (props.inline) ? "float-left mr-2" : "flex justify-start";
case imagePosition.middle:
return "flex justify-center";
case imagePosition.right:
return (props.inline) ? "float-right ml-2" : "flex justify-end";
default:
return undefined;
}
};
const getClassNameWithSpace = (className: string): string => `${ className ? ` ${ className }` : "" }`;
const decorationTypeClass = getDecorationTypeClass();
const sizeTypeClass = getSizeTypeClass();
const positionTypeClass = getPositionTypeClass();
return (<div className={ `not-prose inline-image${ getClassNameWithSpace(positionTypeClass) }` }>
<img className={ `${ decorationTypeClass ? `${ decorationTypeClass }` : "" }${ getClassNameWithSpace(sizeTypeClass) }` }
data-tina-field={ tinaField(props, "imageUrl") }
alt={ props.alt }
src={ props.imageUrl }/>
</div>);
};
export const imageSchema: RichTextTemplate = {
name: "Image",
label: "Advanced Image",
ui: {
defaultItem: {
size: Object.values(imageSize)[0],
decorations: Object.values(imageDecorations)[0]
}
},
fields: [
{
name: "size",
label: "Size",
type: "string",
options: Object.values(imageSize)
},
{
name: "position",
label: "Position",
type: "string",
options: Object.values(imagePosition)
},
{
name: "imageUrl",
label: "Image",
type: "image"
},
{
name: "inline",
label: "Inline",
type: "boolean"
},
{
name: "decorations",
label: "Decorations",
type: "string",
options: Object.values(imageDecorations)
},
{
name: "alt",
label: "Alt",
type: "string"
}
] };
export default Image;

View File

@@ -0,0 +1,48 @@
import { Components } from "tinacms/dist/rich-text";
import BlockQuote, { BlockQuoteProps, blockQuoteSchema } from "./block-quote";
import DateTime, { DateTimeProps, dateTimeSchema } from "./date-time";
import { Prism } from "tinacms/dist/rich-text/prism";
import React from "react";
import Image, { ImageProps, imageSchema } from "./image";
import { RichTextTemplate } from "@tinacms/schema-tools";
import sanitizeHtml from "sanitize-html";
const HTMLInline = (props: { value: string }) => {
const createSanitizedMarkup = (text: string) => {
return { __html: sanitizeHtml(text, {
allowedAttributes: {
div: [ "class" ]
}
}) };
};
return <span dangerouslySetInnerHTML={ createSanitizedMarkup(props.value) } />;
};
const richTextComponents: Components<{
BlockQuote: BlockQuoteProps;
DateTime: DateTimeProps;
Image: ImageProps;
}> = {
code_block: (props) => <Prism { ...props } />,
html: HTMLInline,
img: (props) => (
<span className="flex items-center justify-center">
<img src={ props.url } alt={ props.alt } />
</span>
),
li: (props) => (
<li>{ props.children }</li>
),
BlockQuote,
DateTime,
Image
};
export const richTextTemplates: RichTextTemplate[] = [
dateTimeSchema,
blockQuoteSchema,
imageSchema
];
export default richTextComponents;