@portabletext-typed/to-html
v2.0.1
Published
@portabletext/to-html with typed arguments
Downloads
297
Maintainers
Readme
@portabletext-typed/to-html
@portabletext/to-html with typed arguments
Page Contents
Install
npm install @portabletext/to-html @portabletext-typed/to-html
Usage
After using @sanity-typed/types and @sanity-typed/client and you have typed blocks, use toHTML
from this library as you would from @portabletext/to-html
to get fully typed arguments!
post.ts
:
// import { defineArrayMember, defineField, defineType } from "sanity";
import {
defineArrayMember,
defineField,
defineType,
} from "@sanity-typed/types";
/** No changes using defineType, defineField, and defineArrayMember */
export const post = defineType({
name: "post",
type: "document",
title: "Post",
fields: [
defineField({
name: "content",
type: "array",
title: "Content",
validation: (Rule) => Rule.required(),
of: [
defineArrayMember({ type: "image" }),
defineArrayMember({
type: "block",
of: [defineArrayMember({ type: "file" })],
styles: [
{ title: "Normal", value: "normal" as const },
{ title: "Foo", value: "foo" as const },
],
lists: [
{ title: "Bullet", value: "bullet" as const },
{ title: "Bar", value: "bar" as const },
],
marks: {
decorators: [
{ title: "Strong", value: "strong" as const },
{ title: "Baz", value: "baz" as const },
],
annotations: [
defineArrayMember({
name: "link",
type: "object",
title: "Link",
fields: [
defineField({
name: "href",
type: "string",
validation: (Rule) => Rule.required(),
}),
],
}),
defineArrayMember({
name: "qux",
type: "object",
title: "Qux",
fields: [
defineField({
name: "value",
type: "string",
validation: (Rule) => Rule.required(),
}),
],
}),
],
},
}),
],
}),
],
});
with-portabletext-to-html.tsx
:
import type { InferGetStaticPropsType } from "next";
import { Fragment } from "react";
// import { toHTML } from "@portabletext/to-html";
import { toHTML } from "@portabletext-typed/to-html";
import { client } from "../sanity/client";
export const getStaticProps = async () => ({
props: {
posts: await client.fetch('*[_type=="post"]'),
},
});
const Index = ({ posts }: InferGetStaticPropsType<typeof getStaticProps>) => (
<>
<h1>Posts</h1>
{posts.map(({ _id, content }) => (
<Fragment key={_id}>
<h2>Post</h2>
<div
dangerouslySetInnerHTML={{
// Typed Components!
__html: toHTML(content, {
components: {
types: {
// From Siblings
image: ({ isInline, value }) => `
<div>
typeof ${isInline} === false,
<br />
typeof ${JSON.stringify(value)} === ImageValue,
</div>`,
// From Children
file: ({ isInline, value }) => `
<span>
typeof ${isInline} === true,
typeof ${JSON.stringify(value)} === FileValue,
</span>`,
},
block: {
// Non-Default Styles
foo: ({ children, value }) => `
<div>
typeof ${JSON.stringify(
value
)} === PortableTextBlock\\< ... \\> & { style: "foo" },
${children}
</div>`,
},
list: {
// Non-Default Lists
bar: ({ children, value }) => `
<ul>
<li>typeof ${JSON.stringify(
value
)} === ToolkitPortableTextList & { listItem: "bar"; },</li>
${children}
</ul>`,
},
listItem: {
// Non-Default Lists
bar: ({ children, value }) => `
<li>
typeof ${JSON.stringify(
value
)} === PortableTextBlock\\< ... \\> & { listItem: "bar" },
${children}
</li>`,
},
marks: {
// Non-Default Decorators
baz: ({ children, markKey, markType, value }) => `
<span>
typeof ${value} === undefined,
typeof ${markKey} === "baz",
typeof ${markType} === "baz",
${children}
</span>`,
// Non-Default Annotations
qux: ({ children, markKey, markType, value }) => `
<span>
typeof ${JSON.stringify(value)} === {
_key: string,
_type: "qux",
value: typeof ${value.value} === string,
},
typeof ${markKey} === string,
typeof ${markType} === "qux",
${children}
</span>`,
},
},
}),
}}
/>
</Fragment>
))}
</>
);
export default Index;
Breaking Changes
1 to 2
Typescript version from 5.4.2 <= x <= 5.6.3
The supported Typescript version is now 5.4.2 <= x <= 5.6.3. Older versions are no longer supported and newer versions will be added as we validate it.