@portabletext/sanity-bridge 1.2.11 → 1.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { Schema } from "@sanity/schema";
2
2
  import { builtinTypes } from "@sanity/schema/_internal";
3
3
  import { defineType, defineField, isObjectSchemaType, isArraySchemaType } from "@sanity/types";
4
- import startCase from "lodash.startcase";
5
4
  function createPortableTextMemberSchemaTypes(portableTextType) {
6
5
  if (!portableTextType)
7
6
  throw new Error("Parameter 'portabletextType' missing (required)");
@@ -157,6 +156,9 @@ function randomKey(length) {
157
156
  const table = getByteHexTable();
158
157
  return whatwgRNG(length).reduce((str, n) => str + table[n], "").slice(0, length);
159
158
  }
159
+ function startCase(str) {
160
+ return str.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim().split(/\s+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
161
+ }
160
162
  const temporaryImageBlockObjectName = `tmp-${keyGenerator()}-image`, temporaryUrlBlockObjectName = `tmp-${keyGenerator()}-url`, temporaryImageInlineObjectName = `tmp-${keyGenerator()}-image`, temporaryUrlInlineObjectName = `tmp-${keyGenerator()}-url`, temporaryBlockObjectNames = {
161
163
  image: temporaryImageBlockObjectName,
162
164
  url: temporaryUrlBlockObjectName
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/portable-text-member-schema-types.ts","../src/portable-text-member-schema-types-to-schema.ts","../src/sanity-schema-to-portable-text-schema.ts","../src/key-generator.ts","../src/schema-definition-to-portable-text-member-schema-types.ts"],"sourcesContent":["import type {\n ArraySchemaType,\n BlockDecoratorDefinition,\n BlockListDefinition,\n BlockSchemaType,\n BlockStyleDefinition,\n ObjectSchemaType,\n PortableTextBlock,\n SchemaType,\n SpanSchemaType,\n} from '@sanity/types'\n\n/**\n * @public\n * Sanity-specific schema types for Portable Text.\n */\nexport type PortableTextMemberSchemaTypes = {\n annotations: (ObjectSchemaType & {i18nTitleKey?: string})[]\n block: ObjectSchemaType\n blockObjects: ObjectSchemaType[]\n decorators: BlockDecoratorDefinition[]\n inlineObjects: ObjectSchemaType[]\n portableText: ArraySchemaType<PortableTextBlock>\n span: ObjectSchemaType\n styles: BlockStyleDefinition[]\n lists: BlockListDefinition[]\n}\n\n/**\n * @public\n * Create Sanity-specific schema types for Portable Text from a Sanity array\n * schema type.\n */\nexport function createPortableTextMemberSchemaTypes(\n portableTextType: ArraySchemaType<PortableTextBlock>,\n): PortableTextMemberSchemaTypes {\n if (!portableTextType) {\n throw new Error(\"Parameter 'portabletextType' missing (required)\")\n }\n const blockType = portableTextType.of?.find(findBlockType) as\n | BlockSchemaType\n | undefined\n if (!blockType) {\n throw new Error('Block type is not defined in this schema (required)')\n }\n const childrenField = blockType.fields?.find(\n (field) => field.name === 'children',\n ) as {type: ArraySchemaType} | undefined\n if (!childrenField) {\n throw new Error('Children field for block type found in schema (required)')\n }\n const ofType = childrenField.type.of\n if (!ofType) {\n throw new Error(\n 'Valid types for block children not found in schema (required)',\n )\n }\n const spanType = ofType.find((memberType) => memberType.name === 'span') as\n | ObjectSchemaType\n | undefined\n if (!spanType) {\n throw new Error('Span type not found in schema (required)')\n }\n const inlineObjectTypes = (ofType.filter(\n (memberType) => memberType.name !== 'span',\n ) || []) as ObjectSchemaType[]\n const blockObjectTypes = (portableTextType.of?.filter(\n (field) => field.name !== blockType.name,\n ) || []) as ObjectSchemaType[]\n return {\n styles: resolveEnabledStyles(blockType),\n decorators: resolveEnabledDecorators(spanType),\n lists: resolveEnabledListItems(blockType),\n block: blockType,\n span: spanType,\n portableText: portableTextType,\n inlineObjects: inlineObjectTypes,\n blockObjects: blockObjectTypes,\n annotations: (spanType as SpanSchemaType).annotations,\n }\n}\n\nfunction resolveEnabledStyles(blockType: ObjectSchemaType) {\n const styleField = blockType.fields?.find(\n (btField) => btField.name === 'style',\n )\n if (!styleField) {\n throw new Error(\n \"A field with name 'style' is not defined in the block type (required).\",\n )\n }\n const textStyles =\n styleField.type.options?.list &&\n styleField.type.options.list?.filter(\n (style: {value: string}) => style.value,\n )\n if (!textStyles || textStyles.length === 0) {\n throw new Error(\n 'The style fields need at least one style ' +\n \"defined. I.e: {title: 'Normal', value: 'normal'}.\",\n )\n }\n return textStyles\n}\n\nfunction resolveEnabledDecorators(spanType: ObjectSchemaType) {\n return (spanType as any).decorators\n}\n\nfunction resolveEnabledListItems(blockType: ObjectSchemaType) {\n const listField = blockType.fields?.find(\n (btField) => btField.name === 'listItem',\n )\n if (!listField) {\n throw new Error(\n \"A field with name 'listItem' is not defined in the block type (required).\",\n )\n }\n const listItems =\n listField.type.options?.list &&\n listField.type.options.list.filter((list: {value: string}) => list.value)\n if (!listItems) {\n throw new Error('The list field need at least to be an empty array')\n }\n return listItems\n}\n\nfunction findBlockType(type: SchemaType): BlockSchemaType | null {\n if (type.type) {\n return findBlockType(type.type)\n }\n\n if (type.name === 'block') {\n return type as BlockSchemaType\n }\n\n return null\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {PortableTextMemberSchemaTypes} from './portable-text-member-schema-types'\n\n/**\n * @public\n * Convert Sanity-specific schema types for Portable Text to a first-class\n * Portable Text schema.\n */\nexport function portableTextMemberSchemaTypesToSchema(\n schema: PortableTextMemberSchemaTypes,\n): Schema {\n return {\n annotations: schema.annotations.map((annotation) => ({\n name: annotation.name,\n fields: annotation.fields.map((field) => ({\n name: field.name,\n type: field.type.jsonType,\n title: field.type.title,\n })),\n title: annotation.title,\n })),\n block: {\n name: schema.block.name,\n },\n blockObjects: schema.blockObjects.map((blockObject) => ({\n name: blockObject.name,\n fields: blockObject.fields.map((field) => ({\n name: field.name,\n type: field.type.jsonType,\n title: field.type.title,\n })),\n title: blockObject.title,\n })),\n decorators: schema.decorators.map((decorator) => ({\n name: decorator.value,\n title: decorator.title,\n value: decorator.value,\n })),\n inlineObjects: schema.inlineObjects.map((inlineObject) => ({\n name: inlineObject.name,\n fields: inlineObject.fields.map((field) => ({\n name: field.name,\n type: field.type.jsonType,\n title: field.type.title,\n })),\n title: inlineObject.title,\n })),\n span: {\n name: schema.span.name,\n },\n styles: schema.styles.map((style) => ({\n name: style.value,\n title: style.title,\n value: style.value,\n })),\n lists: schema.lists.map((list) => ({\n name: list.value,\n title: list.title,\n value: list.value,\n })),\n }\n}\n","import type {Schema} from '@portabletext/schema'\nimport {Schema as SanitySchema} from '@sanity/schema'\nimport {builtinTypes} from '@sanity/schema/_internal'\nimport type {ArrayDefinition, ArraySchemaType} from '@sanity/types'\nimport {createPortableTextMemberSchemaTypes} from './portable-text-member-schema-types'\nimport {portableTextMemberSchemaTypesToSchema} from './portable-text-member-schema-types-to-schema'\n\n/**\n * @public\n * Compile a Sanity schema to a Portable Text `Schema`.\n *\n * A Portable Text `Schema` is compatible with a Portable Text\n * `SchemaDefinition` and can be used as configuration for the Portable Text\n * Editor.\n *\n * @example\n * ```tsx\n * const schema = sanitySchemaToPortableTextSchema(sanitySchema)\n *\n * return (\n * <EditorProvider\n * initialConfig={{\n * // ...\n * schemaDefinition: schema,\n * }}\n * >\n * // ...\n * </EditorProvider>\n * ```\n */\nexport function sanitySchemaToPortableTextSchema(\n sanitySchema: ArraySchemaType<unknown> | ArrayDefinition,\n): Schema {\n const portableTextMemberSchemaTypes = createPortableTextMemberSchemaTypes(\n sanitySchema.hasOwnProperty('jsonType')\n ? sanitySchema\n : compileType(sanitySchema),\n )\n\n return portableTextMemberSchemaTypesToSchema(portableTextMemberSchemaTypes)\n}\n\nfunction compileType(rawType: any) {\n return SanitySchema.compile({\n name: 'blockTypeSchema',\n types: [rawType, ...builtinTypes],\n }).get(rawType.name)\n}\n","export const keyGenerator = (): string => randomKey(12)\n\nconst getByteHexTable = (() => {\n let table: any[]\n return () => {\n if (table) {\n return table\n }\n\n table = []\n for (let i = 0; i < 256; ++i) {\n table[i] = (i + 0x100).toString(16).slice(1)\n }\n return table\n }\n})()\n\n// WHATWG crypto RNG - https://w3c.github.io/webcrypto/Overview.html\nfunction whatwgRNG(length = 16) {\n const rnds8 = new Uint8Array(length)\n crypto.getRandomValues(rnds8)\n return rnds8\n}\n\nfunction randomKey(length?: number): string {\n const table = getByteHexTable()\n return whatwgRNG(length)\n .reduce((str, n) => str + table[n], '')\n .slice(0, length)\n}\n","import type {SchemaDefinition} from '@portabletext/schema'\nimport {Schema as SanitySchema} from '@sanity/schema'\nimport {\n defineField,\n defineType,\n isArraySchemaType,\n isObjectSchemaType,\n type ObjectSchemaType,\n} from '@sanity/types'\nimport startCase from 'lodash.startcase'\nimport {keyGenerator} from './key-generator'\nimport {\n createPortableTextMemberSchemaTypes,\n type PortableTextMemberSchemaTypes,\n} from './portable-text-member-schema-types'\n\nconst temporaryImageBlockObjectName = `tmp-${keyGenerator()}-image`\nconst temporaryUrlBlockObjectName = `tmp-${keyGenerator()}-url`\nconst temporaryImageInlineObjectName = `tmp-${keyGenerator()}-image`\nconst temporaryUrlInlineObjectName = `tmp-${keyGenerator()}-url`\n\nconst temporaryBlockObjectNames: Record<string, string> = {\n image: temporaryImageBlockObjectName,\n url: temporaryUrlBlockObjectName,\n}\n\nconst temporaryInlineObjectNames: Record<string, string> = {\n image: temporaryImageInlineObjectName,\n url: temporaryUrlInlineObjectName,\n}\n\nconst blockObjectNames: Record<string, string> = {\n [temporaryImageBlockObjectName]: 'image',\n [temporaryUrlBlockObjectName]: 'url',\n}\n\nconst inlineObjectNames: Record<string, string> = {\n [temporaryImageInlineObjectName]: 'image',\n [temporaryUrlInlineObjectName]: 'url',\n}\n\nconst defaultObjectTitles: Record<string, string> = {\n image: 'Image',\n url: 'URL',\n}\n\n/**\n * @public\n * Compile a Portable Text schema definition to Sanity-specific schema types for\n * Portable Text.\n */\nexport function compileSchemaDefinitionToPortableTextMemberSchemaTypes(\n definition?: SchemaDefinition,\n): PortableTextMemberSchemaTypes {\n const blockObjects =\n definition?.blockObjects?.map((blockObject) =>\n defineType({\n type: 'object',\n // Very naive way to work around `SanitySchema.compile` adding default\n // fields to objects with certain names.\n name: temporaryBlockObjectNames[blockObject.name] ?? blockObject.name,\n title:\n blockObject.title === undefined\n ? // This avoids the default title which is a title case of the object name\n defaultObjectTitles[blockObject.name]\n : blockObject.title,\n fields:\n blockObject.fields?.map((field) => ({\n name: field.name,\n type: field.type,\n title: field.title ?? startCase(field.name),\n })) ?? [],\n }),\n ) ?? []\n\n const inlineObjects =\n definition?.inlineObjects?.map((inlineObject) =>\n defineType({\n type: 'object',\n // Very naive way to work around `SanitySchema.compile` adding default\n // fields to objects with certain names.\n name:\n temporaryInlineObjectNames[inlineObject.name] ?? inlineObject.name,\n\n title:\n inlineObject.title === undefined\n ? // This avoids the default title which is a title case of the object name\n defaultObjectTitles[inlineObject.name]\n : inlineObject.title,\n fields:\n inlineObject.fields?.map((field) => ({\n name: field.name,\n type: field.type,\n title: field.title ?? startCase(field.name),\n })) ?? [],\n }),\n ) ?? []\n\n const portableTextSchema = defineField({\n type: 'array',\n name: 'portable-text',\n of: [\n ...blockObjects.map((blockObject) => ({type: blockObject.name})),\n {\n type: 'block',\n name: 'block',\n of: inlineObjects.map((inlineObject) => ({type: inlineObject.name})),\n marks: {\n decorators:\n definition?.decorators?.map((decorator) => ({\n title: decorator.title ?? startCase(decorator.name),\n value: decorator.name,\n })) ?? [],\n annotations:\n definition?.annotations?.map((annotation) => ({\n name: annotation.name,\n type: 'object',\n title: annotation.title,\n fields:\n annotation.fields?.map((field) => ({\n name: field.name,\n title: field.title ?? startCase(field.name),\n type: field.type,\n })) ?? [],\n })) ?? [],\n },\n lists:\n definition?.lists?.map((list) => ({\n value: list.name,\n title: list.title ?? startCase(list.name),\n })) ?? [],\n styles:\n definition?.styles?.map((style) => ({\n value: style.name,\n title: style.title ?? startCase(style.name),\n })) ?? [],\n },\n ],\n })\n\n const schema = SanitySchema.compile({\n types: [portableTextSchema, ...blockObjects, ...inlineObjects],\n }).get('portable-text')\n\n const pteSchema = createPortableTextMemberSchemaTypes(schema)\n\n return {\n ...pteSchema,\n portableText: {\n ...pteSchema.portableText,\n of: pteSchema.portableText.of.map((schemaType) => {\n if (!isObjectSchemaType(schemaType)) {\n return schemaType\n }\n\n const nameMapping = blockObjectNames[schemaType.name]\n\n schemaType.name = nameMapping ?? schemaType.name\n\n for (const field of schemaType.fields) {\n if (field.name !== 'children' || !isArraySchemaType(field.type)) {\n continue\n }\n\n for (const ofSchemaType of field.type.of) {\n const nameMapping = inlineObjectNames[ofSchemaType.name]\n\n if (!nameMapping) {\n continue\n }\n\n ofSchemaType.name = nameMapping\n }\n }\n\n return schemaType\n }),\n },\n blockObjects: pteSchema.blockObjects.map((blockObject) =>\n blockObjectNames[blockObject.name] !== undefined\n ? ({\n ...blockObject,\n name: blockObjectNames[blockObject.name],\n type: {\n ...blockObject.type,\n name: blockObjectNames[blockObject.name],\n },\n } as ObjectSchemaType)\n : blockObject,\n ),\n inlineObjects: pteSchema.inlineObjects.map((inlineObject) =>\n inlineObjectNames[inlineObject.name] !== undefined\n ? ({\n ...inlineObject,\n name: inlineObjectNames[inlineObject.name],\n } as ObjectSchemaType)\n : inlineObject,\n ),\n } satisfies PortableTextMemberSchemaTypes\n}\n"],"names":["SanitySchema","nameMapping"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/portable-text-member-schema-types.ts","../src/portable-text-member-schema-types-to-schema.ts","../src/sanity-schema-to-portable-text-schema.ts","../src/key-generator.ts","../src/start-case.ts","../src/schema-definition-to-portable-text-member-schema-types.ts"],"sourcesContent":["import type {\n ArraySchemaType,\n BlockDecoratorDefinition,\n BlockListDefinition,\n BlockSchemaType,\n BlockStyleDefinition,\n ObjectSchemaType,\n PortableTextBlock,\n SchemaType,\n SpanSchemaType,\n} from '@sanity/types'\n\n/**\n * @public\n * Sanity-specific schema types for Portable Text.\n */\nexport type PortableTextMemberSchemaTypes = {\n annotations: (ObjectSchemaType & {i18nTitleKey?: string})[]\n block: ObjectSchemaType\n blockObjects: ObjectSchemaType[]\n decorators: BlockDecoratorDefinition[]\n inlineObjects: ObjectSchemaType[]\n portableText: ArraySchemaType<PortableTextBlock>\n span: ObjectSchemaType\n styles: BlockStyleDefinition[]\n lists: BlockListDefinition[]\n}\n\n/**\n * @public\n * Create Sanity-specific schema types for Portable Text from a Sanity array\n * schema type.\n */\nexport function createPortableTextMemberSchemaTypes(\n portableTextType: ArraySchemaType<PortableTextBlock>,\n): PortableTextMemberSchemaTypes {\n if (!portableTextType) {\n throw new Error(\"Parameter 'portabletextType' missing (required)\")\n }\n const blockType = portableTextType.of?.find(findBlockType) as\n | BlockSchemaType\n | undefined\n if (!blockType) {\n throw new Error('Block type is not defined in this schema (required)')\n }\n const childrenField = blockType.fields?.find(\n (field) => field.name === 'children',\n ) as {type: ArraySchemaType} | undefined\n if (!childrenField) {\n throw new Error('Children field for block type found in schema (required)')\n }\n const ofType = childrenField.type.of\n if (!ofType) {\n throw new Error(\n 'Valid types for block children not found in schema (required)',\n )\n }\n const spanType = ofType.find((memberType) => memberType.name === 'span') as\n | ObjectSchemaType\n | undefined\n if (!spanType) {\n throw new Error('Span type not found in schema (required)')\n }\n const inlineObjectTypes = (ofType.filter(\n (memberType) => memberType.name !== 'span',\n ) || []) as ObjectSchemaType[]\n const blockObjectTypes = (portableTextType.of?.filter(\n (field) => field.name !== blockType.name,\n ) || []) as ObjectSchemaType[]\n return {\n styles: resolveEnabledStyles(blockType),\n decorators: resolveEnabledDecorators(spanType),\n lists: resolveEnabledListItems(blockType),\n block: blockType,\n span: spanType,\n portableText: portableTextType,\n inlineObjects: inlineObjectTypes,\n blockObjects: blockObjectTypes,\n annotations: (spanType as SpanSchemaType).annotations,\n }\n}\n\nfunction resolveEnabledStyles(blockType: ObjectSchemaType) {\n const styleField = blockType.fields?.find(\n (btField) => btField.name === 'style',\n )\n if (!styleField) {\n throw new Error(\n \"A field with name 'style' is not defined in the block type (required).\",\n )\n }\n const textStyles =\n styleField.type.options?.list &&\n styleField.type.options.list?.filter(\n (style: {value: string}) => style.value,\n )\n if (!textStyles || textStyles.length === 0) {\n throw new Error(\n 'The style fields need at least one style ' +\n \"defined. I.e: {title: 'Normal', value: 'normal'}.\",\n )\n }\n return textStyles\n}\n\nfunction resolveEnabledDecorators(spanType: ObjectSchemaType) {\n return (spanType as any).decorators\n}\n\nfunction resolveEnabledListItems(blockType: ObjectSchemaType) {\n const listField = blockType.fields?.find(\n (btField) => btField.name === 'listItem',\n )\n if (!listField) {\n throw new Error(\n \"A field with name 'listItem' is not defined in the block type (required).\",\n )\n }\n const listItems =\n listField.type.options?.list &&\n listField.type.options.list.filter((list: {value: string}) => list.value)\n if (!listItems) {\n throw new Error('The list field need at least to be an empty array')\n }\n return listItems\n}\n\nfunction findBlockType(type: SchemaType): BlockSchemaType | null {\n if (type.type) {\n return findBlockType(type.type)\n }\n\n if (type.name === 'block') {\n return type as BlockSchemaType\n }\n\n return null\n}\n","import type {Schema} from '@portabletext/schema'\nimport type {PortableTextMemberSchemaTypes} from './portable-text-member-schema-types'\n\n/**\n * @public\n * Convert Sanity-specific schema types for Portable Text to a first-class\n * Portable Text schema.\n */\nexport function portableTextMemberSchemaTypesToSchema(\n schema: PortableTextMemberSchemaTypes,\n): Schema {\n return {\n annotations: schema.annotations.map((annotation) => ({\n name: annotation.name,\n fields: annotation.fields.map((field) => ({\n name: field.name,\n type: field.type.jsonType,\n title: field.type.title,\n })),\n title: annotation.title,\n })),\n block: {\n name: schema.block.name,\n },\n blockObjects: schema.blockObjects.map((blockObject) => ({\n name: blockObject.name,\n fields: blockObject.fields.map((field) => ({\n name: field.name,\n type: field.type.jsonType,\n title: field.type.title,\n })),\n title: blockObject.title,\n })),\n decorators: schema.decorators.map((decorator) => ({\n name: decorator.value,\n title: decorator.title,\n value: decorator.value,\n })),\n inlineObjects: schema.inlineObjects.map((inlineObject) => ({\n name: inlineObject.name,\n fields: inlineObject.fields.map((field) => ({\n name: field.name,\n type: field.type.jsonType,\n title: field.type.title,\n })),\n title: inlineObject.title,\n })),\n span: {\n name: schema.span.name,\n },\n styles: schema.styles.map((style) => ({\n name: style.value,\n title: style.title,\n value: style.value,\n })),\n lists: schema.lists.map((list) => ({\n name: list.value,\n title: list.title,\n value: list.value,\n })),\n }\n}\n","import type {Schema} from '@portabletext/schema'\nimport {Schema as SanitySchema} from '@sanity/schema'\nimport {builtinTypes} from '@sanity/schema/_internal'\nimport type {ArrayDefinition, ArraySchemaType} from '@sanity/types'\nimport {createPortableTextMemberSchemaTypes} from './portable-text-member-schema-types'\nimport {portableTextMemberSchemaTypesToSchema} from './portable-text-member-schema-types-to-schema'\n\n/**\n * @public\n * Compile a Sanity schema to a Portable Text `Schema`.\n *\n * A Portable Text `Schema` is compatible with a Portable Text\n * `SchemaDefinition` and can be used as configuration for the Portable Text\n * Editor.\n *\n * @example\n * ```tsx\n * const schema = sanitySchemaToPortableTextSchema(sanitySchema)\n *\n * return (\n * <EditorProvider\n * initialConfig={{\n * // ...\n * schemaDefinition: schema,\n * }}\n * >\n * // ...\n * </EditorProvider>\n * ```\n */\nexport function sanitySchemaToPortableTextSchema(\n sanitySchema: ArraySchemaType<unknown> | ArrayDefinition,\n): Schema {\n const portableTextMemberSchemaTypes = createPortableTextMemberSchemaTypes(\n sanitySchema.hasOwnProperty('jsonType')\n ? sanitySchema\n : compileType(sanitySchema),\n )\n\n return portableTextMemberSchemaTypesToSchema(portableTextMemberSchemaTypes)\n}\n\nfunction compileType(rawType: any) {\n return SanitySchema.compile({\n name: 'blockTypeSchema',\n types: [rawType, ...builtinTypes],\n }).get(rawType.name)\n}\n","export const keyGenerator = (): string => randomKey(12)\n\nconst getByteHexTable = (() => {\n let table: any[]\n return () => {\n if (table) {\n return table\n }\n\n table = []\n for (let i = 0; i < 256; ++i) {\n table[i] = (i + 0x100).toString(16).slice(1)\n }\n return table\n }\n})()\n\n// WHATWG crypto RNG - https://w3c.github.io/webcrypto/Overview.html\nfunction whatwgRNG(length = 16) {\n const rnds8 = new Uint8Array(length)\n crypto.getRandomValues(rnds8)\n return rnds8\n}\n\nfunction randomKey(length?: number): string {\n const table = getByteHexTable()\n return whatwgRNG(length)\n .reduce((str, n) => str + table[n], '')\n .slice(0, length)\n}\n","export function startCase(str: string): string {\n return (\n str\n // Insert space before uppercase letters in camelCase (e.g., 'fooBar' -> 'foo Bar')\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Replace underscores and dashes with spaces\n .replace(/[_-]+/g, ' ')\n // Trim and split on whitespace\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n // Capitalize first letter of each word, preserve rest\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ')\n )\n}\n","import type {SchemaDefinition} from '@portabletext/schema'\nimport {Schema as SanitySchema} from '@sanity/schema'\nimport {\n defineField,\n defineType,\n isArraySchemaType,\n isObjectSchemaType,\n type ObjectSchemaType,\n} from '@sanity/types'\nimport {keyGenerator} from './key-generator'\nimport {\n createPortableTextMemberSchemaTypes,\n type PortableTextMemberSchemaTypes,\n} from './portable-text-member-schema-types'\nimport {startCase} from './start-case'\n\nconst temporaryImageBlockObjectName = `tmp-${keyGenerator()}-image`\nconst temporaryUrlBlockObjectName = `tmp-${keyGenerator()}-url`\nconst temporaryImageInlineObjectName = `tmp-${keyGenerator()}-image`\nconst temporaryUrlInlineObjectName = `tmp-${keyGenerator()}-url`\n\nconst temporaryBlockObjectNames: Record<string, string> = {\n image: temporaryImageBlockObjectName,\n url: temporaryUrlBlockObjectName,\n}\n\nconst temporaryInlineObjectNames: Record<string, string> = {\n image: temporaryImageInlineObjectName,\n url: temporaryUrlInlineObjectName,\n}\n\nconst blockObjectNames: Record<string, string> = {\n [temporaryImageBlockObjectName]: 'image',\n [temporaryUrlBlockObjectName]: 'url',\n}\n\nconst inlineObjectNames: Record<string, string> = {\n [temporaryImageInlineObjectName]: 'image',\n [temporaryUrlInlineObjectName]: 'url',\n}\n\nconst defaultObjectTitles: Record<string, string> = {\n image: 'Image',\n url: 'URL',\n}\n\n/**\n * @public\n * Compile a Portable Text schema definition to Sanity-specific schema types for\n * Portable Text.\n */\nexport function compileSchemaDefinitionToPortableTextMemberSchemaTypes(\n definition?: SchemaDefinition,\n): PortableTextMemberSchemaTypes {\n const blockObjects =\n definition?.blockObjects?.map((blockObject) =>\n defineType({\n type: 'object',\n // Very naive way to work around `SanitySchema.compile` adding default\n // fields to objects with certain names.\n name: temporaryBlockObjectNames[blockObject.name] ?? blockObject.name,\n title:\n blockObject.title === undefined\n ? // This avoids the default title which is a title case of the object name\n defaultObjectTitles[blockObject.name]\n : blockObject.title,\n fields:\n blockObject.fields?.map((field) => ({\n name: field.name,\n type: field.type,\n title: field.title ?? startCase(field.name),\n })) ?? [],\n }),\n ) ?? []\n\n const inlineObjects =\n definition?.inlineObjects?.map((inlineObject) =>\n defineType({\n type: 'object',\n // Very naive way to work around `SanitySchema.compile` adding default\n // fields to objects with certain names.\n name:\n temporaryInlineObjectNames[inlineObject.name] ?? inlineObject.name,\n\n title:\n inlineObject.title === undefined\n ? // This avoids the default title which is a title case of the object name\n defaultObjectTitles[inlineObject.name]\n : inlineObject.title,\n fields:\n inlineObject.fields?.map((field) => ({\n name: field.name,\n type: field.type,\n title: field.title ?? startCase(field.name),\n })) ?? [],\n }),\n ) ?? []\n\n const portableTextSchema = defineField({\n type: 'array',\n name: 'portable-text',\n of: [\n ...blockObjects.map((blockObject) => ({type: blockObject.name})),\n {\n type: 'block',\n name: 'block',\n of: inlineObjects.map((inlineObject) => ({type: inlineObject.name})),\n marks: {\n decorators:\n definition?.decorators?.map((decorator) => ({\n title: decorator.title ?? startCase(decorator.name),\n value: decorator.name,\n })) ?? [],\n annotations:\n definition?.annotations?.map((annotation) => ({\n name: annotation.name,\n type: 'object',\n title: annotation.title,\n fields:\n annotation.fields?.map((field) => ({\n name: field.name,\n title: field.title ?? startCase(field.name),\n type: field.type,\n })) ?? [],\n })) ?? [],\n },\n lists:\n definition?.lists?.map((list) => ({\n value: list.name,\n title: list.title ?? startCase(list.name),\n })) ?? [],\n styles:\n definition?.styles?.map((style) => ({\n value: style.name,\n title: style.title ?? startCase(style.name),\n })) ?? [],\n },\n ],\n })\n\n const schema = SanitySchema.compile({\n types: [portableTextSchema, ...blockObjects, ...inlineObjects],\n }).get('portable-text')\n\n const pteSchema = createPortableTextMemberSchemaTypes(schema)\n\n return {\n ...pteSchema,\n portableText: {\n ...pteSchema.portableText,\n of: pteSchema.portableText.of.map((schemaType) => {\n if (!isObjectSchemaType(schemaType)) {\n return schemaType\n }\n\n const nameMapping = blockObjectNames[schemaType.name]\n\n schemaType.name = nameMapping ?? schemaType.name\n\n for (const field of schemaType.fields) {\n if (field.name !== 'children' || !isArraySchemaType(field.type)) {\n continue\n }\n\n for (const ofSchemaType of field.type.of) {\n const nameMapping = inlineObjectNames[ofSchemaType.name]\n\n if (!nameMapping) {\n continue\n }\n\n ofSchemaType.name = nameMapping\n }\n }\n\n return schemaType\n }),\n },\n blockObjects: pteSchema.blockObjects.map((blockObject) =>\n blockObjectNames[blockObject.name] !== undefined\n ? ({\n ...blockObject,\n name: blockObjectNames[blockObject.name],\n type: {\n ...blockObject.type,\n name: blockObjectNames[blockObject.name],\n },\n } as ObjectSchemaType)\n : blockObject,\n ),\n inlineObjects: pteSchema.inlineObjects.map((inlineObject) =>\n inlineObjectNames[inlineObject.name] !== undefined\n ? ({\n ...inlineObject,\n name: inlineObjectNames[inlineObject.name],\n } as ObjectSchemaType)\n : inlineObject,\n ),\n } satisfies PortableTextMemberSchemaTypes\n}\n"],"names":["SanitySchema","nameMapping"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/sanity-bridge",
3
- "version": "1.2.11",
3
+ "version": "1.2.13",
4
4
  "description": "Convert a Sanity Schema to a Portable Text Schema",
5
5
  "keywords": [
6
6
  "sanity",
@@ -29,19 +29,16 @@
29
29
  "main": "./dist/index.js",
30
30
  "types": "./dist/index.d.ts",
31
31
  "files": [
32
- "dist",
33
- "src"
32
+ "dist"
34
33
  ],
35
34
  "dependencies": {
36
35
  "@sanity/schema": "^4.20.3",
37
36
  "@sanity/types": "^4.20.3",
38
- "lodash.startcase": "^4.4.0",
39
- "@portabletext/schema": "^2.0.0"
37
+ "@portabletext/schema": "^2.0.1"
40
38
  },
41
39
  "devDependencies": {
42
- "@sanity/pkg-utils": "^10.1.1",
43
- "@sanity/tsconfig": "^1.0.0",
44
- "@types/lodash.startcase": "^4.4.9",
40
+ "@sanity/pkg-utils": "^10.1.2",
41
+ "@sanity/tsconfig": "^2.0.0",
45
42
  "typescript": "5.9.3",
46
43
  "vitest": "^4.0.14"
47
44
  },
package/src/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export {
2
- createPortableTextMemberSchemaTypes,
3
- type PortableTextMemberSchemaTypes,
4
- } from './portable-text-member-schema-types'
5
- export {portableTextMemberSchemaTypesToSchema} from './portable-text-member-schema-types-to-schema'
6
- export {sanitySchemaToPortableTextSchema} from './sanity-schema-to-portable-text-schema'
7
- export {compileSchemaDefinitionToPortableTextMemberSchemaTypes} from './schema-definition-to-portable-text-member-schema-types'
@@ -1,30 +0,0 @@
1
- export const keyGenerator = (): string => randomKey(12)
2
-
3
- const getByteHexTable = (() => {
4
- let table: any[]
5
- return () => {
6
- if (table) {
7
- return table
8
- }
9
-
10
- table = []
11
- for (let i = 0; i < 256; ++i) {
12
- table[i] = (i + 0x100).toString(16).slice(1)
13
- }
14
- return table
15
- }
16
- })()
17
-
18
- // WHATWG crypto RNG - https://w3c.github.io/webcrypto/Overview.html
19
- function whatwgRNG(length = 16) {
20
- const rnds8 = new Uint8Array(length)
21
- crypto.getRandomValues(rnds8)
22
- return rnds8
23
- }
24
-
25
- function randomKey(length?: number): string {
26
- const table = getByteHexTable()
27
- return whatwgRNG(length)
28
- .reduce((str, n) => str + table[n], '')
29
- .slice(0, length)
30
- }
@@ -1,62 +0,0 @@
1
- import type {Schema} from '@portabletext/schema'
2
- import type {PortableTextMemberSchemaTypes} from './portable-text-member-schema-types'
3
-
4
- /**
5
- * @public
6
- * Convert Sanity-specific schema types for Portable Text to a first-class
7
- * Portable Text schema.
8
- */
9
- export function portableTextMemberSchemaTypesToSchema(
10
- schema: PortableTextMemberSchemaTypes,
11
- ): Schema {
12
- return {
13
- annotations: schema.annotations.map((annotation) => ({
14
- name: annotation.name,
15
- fields: annotation.fields.map((field) => ({
16
- name: field.name,
17
- type: field.type.jsonType,
18
- title: field.type.title,
19
- })),
20
- title: annotation.title,
21
- })),
22
- block: {
23
- name: schema.block.name,
24
- },
25
- blockObjects: schema.blockObjects.map((blockObject) => ({
26
- name: blockObject.name,
27
- fields: blockObject.fields.map((field) => ({
28
- name: field.name,
29
- type: field.type.jsonType,
30
- title: field.type.title,
31
- })),
32
- title: blockObject.title,
33
- })),
34
- decorators: schema.decorators.map((decorator) => ({
35
- name: decorator.value,
36
- title: decorator.title,
37
- value: decorator.value,
38
- })),
39
- inlineObjects: schema.inlineObjects.map((inlineObject) => ({
40
- name: inlineObject.name,
41
- fields: inlineObject.fields.map((field) => ({
42
- name: field.name,
43
- type: field.type.jsonType,
44
- title: field.type.title,
45
- })),
46
- title: inlineObject.title,
47
- })),
48
- span: {
49
- name: schema.span.name,
50
- },
51
- styles: schema.styles.map((style) => ({
52
- name: style.value,
53
- title: style.title,
54
- value: style.value,
55
- })),
56
- lists: schema.lists.map((list) => ({
57
- name: list.value,
58
- title: list.title,
59
- value: list.value,
60
- })),
61
- }
62
- }
@@ -1,138 +0,0 @@
1
- import type {
2
- ArraySchemaType,
3
- BlockDecoratorDefinition,
4
- BlockListDefinition,
5
- BlockSchemaType,
6
- BlockStyleDefinition,
7
- ObjectSchemaType,
8
- PortableTextBlock,
9
- SchemaType,
10
- SpanSchemaType,
11
- } from '@sanity/types'
12
-
13
- /**
14
- * @public
15
- * Sanity-specific schema types for Portable Text.
16
- */
17
- export type PortableTextMemberSchemaTypes = {
18
- annotations: (ObjectSchemaType & {i18nTitleKey?: string})[]
19
- block: ObjectSchemaType
20
- blockObjects: ObjectSchemaType[]
21
- decorators: BlockDecoratorDefinition[]
22
- inlineObjects: ObjectSchemaType[]
23
- portableText: ArraySchemaType<PortableTextBlock>
24
- span: ObjectSchemaType
25
- styles: BlockStyleDefinition[]
26
- lists: BlockListDefinition[]
27
- }
28
-
29
- /**
30
- * @public
31
- * Create Sanity-specific schema types for Portable Text from a Sanity array
32
- * schema type.
33
- */
34
- export function createPortableTextMemberSchemaTypes(
35
- portableTextType: ArraySchemaType<PortableTextBlock>,
36
- ): PortableTextMemberSchemaTypes {
37
- if (!portableTextType) {
38
- throw new Error("Parameter 'portabletextType' missing (required)")
39
- }
40
- const blockType = portableTextType.of?.find(findBlockType) as
41
- | BlockSchemaType
42
- | undefined
43
- if (!blockType) {
44
- throw new Error('Block type is not defined in this schema (required)')
45
- }
46
- const childrenField = blockType.fields?.find(
47
- (field) => field.name === 'children',
48
- ) as {type: ArraySchemaType} | undefined
49
- if (!childrenField) {
50
- throw new Error('Children field for block type found in schema (required)')
51
- }
52
- const ofType = childrenField.type.of
53
- if (!ofType) {
54
- throw new Error(
55
- 'Valid types for block children not found in schema (required)',
56
- )
57
- }
58
- const spanType = ofType.find((memberType) => memberType.name === 'span') as
59
- | ObjectSchemaType
60
- | undefined
61
- if (!spanType) {
62
- throw new Error('Span type not found in schema (required)')
63
- }
64
- const inlineObjectTypes = (ofType.filter(
65
- (memberType) => memberType.name !== 'span',
66
- ) || []) as ObjectSchemaType[]
67
- const blockObjectTypes = (portableTextType.of?.filter(
68
- (field) => field.name !== blockType.name,
69
- ) || []) as ObjectSchemaType[]
70
- return {
71
- styles: resolveEnabledStyles(blockType),
72
- decorators: resolveEnabledDecorators(spanType),
73
- lists: resolveEnabledListItems(blockType),
74
- block: blockType,
75
- span: spanType,
76
- portableText: portableTextType,
77
- inlineObjects: inlineObjectTypes,
78
- blockObjects: blockObjectTypes,
79
- annotations: (spanType as SpanSchemaType).annotations,
80
- }
81
- }
82
-
83
- function resolveEnabledStyles(blockType: ObjectSchemaType) {
84
- const styleField = blockType.fields?.find(
85
- (btField) => btField.name === 'style',
86
- )
87
- if (!styleField) {
88
- throw new Error(
89
- "A field with name 'style' is not defined in the block type (required).",
90
- )
91
- }
92
- const textStyles =
93
- styleField.type.options?.list &&
94
- styleField.type.options.list?.filter(
95
- (style: {value: string}) => style.value,
96
- )
97
- if (!textStyles || textStyles.length === 0) {
98
- throw new Error(
99
- 'The style fields need at least one style ' +
100
- "defined. I.e: {title: 'Normal', value: 'normal'}.",
101
- )
102
- }
103
- return textStyles
104
- }
105
-
106
- function resolveEnabledDecorators(spanType: ObjectSchemaType) {
107
- return (spanType as any).decorators
108
- }
109
-
110
- function resolveEnabledListItems(blockType: ObjectSchemaType) {
111
- const listField = blockType.fields?.find(
112
- (btField) => btField.name === 'listItem',
113
- )
114
- if (!listField) {
115
- throw new Error(
116
- "A field with name 'listItem' is not defined in the block type (required).",
117
- )
118
- }
119
- const listItems =
120
- listField.type.options?.list &&
121
- listField.type.options.list.filter((list: {value: string}) => list.value)
122
- if (!listItems) {
123
- throw new Error('The list field need at least to be an empty array')
124
- }
125
- return listItems
126
- }
127
-
128
- function findBlockType(type: SchemaType): BlockSchemaType | null {
129
- if (type.type) {
130
- return findBlockType(type.type)
131
- }
132
-
133
- if (type.name === 'block') {
134
- return type as BlockSchemaType
135
- }
136
-
137
- return null
138
- }
@@ -1,299 +0,0 @@
1
- import type {Schema} from '@portabletext/schema'
2
- import {Schema as SanitySchema} from '@sanity/schema'
3
- import {builtinTypes} from '@sanity/schema/_internal'
4
- import {
5
- defineArrayMember,
6
- defineField,
7
- defineType,
8
- type ArrayDefinition,
9
- } from '@sanity/types'
10
- import {describe, expect, test} from 'vitest'
11
- import {createPortableTextMemberSchemaTypes} from './portable-text-member-schema-types'
12
- import {portableTextMemberSchemaTypesToSchema} from './portable-text-member-schema-types-to-schema'
13
- import {sanitySchemaToPortableTextSchema} from './sanity-schema-to-portable-text-schema'
14
- import {compileSchemaDefinitionToPortableTextMemberSchemaTypes} from './schema-definition-to-portable-text-member-schema-types'
15
-
16
- describe(sanitySchemaToPortableTextSchema.name, () => {
17
- const defaultSchema: Schema = {
18
- block: {
19
- name: 'block',
20
- },
21
- span: {
22
- name: 'span',
23
- },
24
- styles: [
25
- {
26
- name: 'normal',
27
- value: 'normal',
28
- title: 'Normal',
29
- },
30
- {
31
- name: 'h1',
32
- value: 'h1',
33
- title: 'Heading 1',
34
- },
35
- {
36
- name: 'h2',
37
- value: 'h2',
38
- title: 'Heading 2',
39
- },
40
- {
41
- name: 'h3',
42
- value: 'h3',
43
- title: 'Heading 3',
44
- },
45
- {
46
- name: 'h4',
47
- value: 'h4',
48
- title: 'Heading 4',
49
- },
50
- {
51
- name: 'h5',
52
- value: 'h5',
53
- title: 'Heading 5',
54
- },
55
- {
56
- name: 'h6',
57
- value: 'h6',
58
- title: 'Heading 6',
59
- },
60
- {
61
- name: 'blockquote',
62
- value: 'blockquote',
63
- title: 'Quote',
64
- },
65
- ],
66
- lists: [
67
- {
68
- name: 'bullet',
69
- value: 'bullet',
70
- title: 'Bulleted list',
71
- },
72
- {
73
- name: 'number',
74
- value: 'number',
75
- title: 'Numbered list',
76
- },
77
- ],
78
- decorators: [
79
- {
80
- name: 'strong',
81
- value: 'strong',
82
- title: 'Strong',
83
- },
84
- {
85
- name: 'em',
86
- value: 'em',
87
- title: 'Italic',
88
- },
89
- {
90
- name: 'code',
91
- value: 'code',
92
- title: 'Code',
93
- },
94
- {
95
- name: 'underline',
96
- value: 'underline',
97
- title: 'Underline',
98
- },
99
- {
100
- name: 'strike-through',
101
- value: 'strike-through',
102
- title: 'Strike',
103
- },
104
- ],
105
- annotations: [
106
- {
107
- name: 'link',
108
- title: 'Link',
109
- fields: [
110
- {
111
- name: 'href',
112
- type: 'string',
113
- title: 'Link',
114
- },
115
- ],
116
- },
117
- ],
118
- blockObjects: [],
119
- inlineObjects: [],
120
- }
121
-
122
- test('simple compiled schema', () => {
123
- const sanitySchema = SanitySchema.compile({
124
- name: 'test',
125
- types: [
126
- defineArrayMember({
127
- type: 'array',
128
- name: 'content',
129
- of: [defineField({type: 'block', name: 'block'})],
130
- }),
131
- ],
132
- })
133
-
134
- expect(
135
- sanitySchemaToPortableTextSchema(sanitySchema.get('content')),
136
- ).toEqual(defaultSchema)
137
- })
138
-
139
- test('schema with built-in types', () => {
140
- const sanitySchema = SanitySchema.compile({
141
- name: 'test',
142
- types: [
143
- defineArrayMember({
144
- type: 'array',
145
- name: 'content',
146
- of: [
147
- defineField({
148
- type: 'block',
149
- name: 'block',
150
- }),
151
- defineField({type: 'image', name: 'image'}),
152
- ],
153
- }),
154
- ...builtinTypes,
155
- ],
156
- })
157
-
158
- expect(
159
- sanitySchemaToPortableTextSchema(sanitySchema.get('content'))
160
- .blockObjects,
161
- ).toEqual([
162
- {
163
- name: 'image',
164
- title: 'Image',
165
- fields: [
166
- {
167
- name: 'asset',
168
- title: 'Asset',
169
- type: 'object',
170
- },
171
- {
172
- name: 'media',
173
- title: 'Media',
174
- type: 'object',
175
- },
176
- {
177
- name: 'hotspot',
178
- title: 'Hotspot',
179
- type: 'object',
180
- },
181
- {
182
- name: 'crop',
183
- title: 'Crop',
184
- type: 'object',
185
- },
186
- ],
187
- },
188
- ])
189
- })
190
-
191
- test('simple array definition', () => {
192
- const sanitySchema: ArrayDefinition = {
193
- type: 'array',
194
- name: 'content',
195
- of: [defineField({type: 'block', name: 'block'})],
196
- }
197
-
198
- expect(sanitySchemaToPortableTextSchema(sanitySchema)).toEqual(
199
- defaultSchema,
200
- )
201
- })
202
-
203
- test('array definition with image', () => {
204
- const sanitySchema: ArrayDefinition = {
205
- type: 'array',
206
- name: 'content',
207
- of: [
208
- defineField({type: 'block', name: 'block'}),
209
- defineField({type: 'image', name: 'image'}),
210
- ],
211
- }
212
-
213
- expect(sanitySchemaToPortableTextSchema(sanitySchema)).toEqual({
214
- ...defaultSchema,
215
- blockObjects: [
216
- ...defaultSchema.blockObjects,
217
- {
218
- name: 'image',
219
- title: 'Image',
220
- fields: [
221
- {
222
- name: 'asset',
223
- title: 'Asset',
224
- type: 'object',
225
- },
226
- {
227
- name: 'media',
228
- title: 'Media',
229
- type: 'object',
230
- },
231
- {
232
- name: 'hotspot',
233
- title: 'Hotspot',
234
- type: 'object',
235
- },
236
- {
237
- name: 'crop',
238
- title: 'Crop',
239
- type: 'object',
240
- },
241
- ],
242
- },
243
- ],
244
- })
245
- })
246
-
247
- test('compiled back and forth', () => {
248
- const imageType = defineType({
249
- name: 'custom image',
250
- type: 'object',
251
- fields: [
252
- defineField({
253
- name: 'url',
254
- type: 'string',
255
- }),
256
- ],
257
- })
258
- const stockTickerType = defineType({
259
- name: 'stock ticker',
260
- type: 'object',
261
- fields: [defineField({name: 'symbol', type: 'string'})],
262
- })
263
- const portableTextType = defineType({
264
- type: 'array',
265
- name: 'body',
266
- of: [
267
- {
268
- type: 'block',
269
- name: 'block',
270
- of: [{type: 'stock ticker'}],
271
- },
272
- {type: 'custom image'},
273
- ],
274
- })
275
-
276
- const sanitySchema = SanitySchema.compile({
277
- types: [portableTextType, imageType, stockTickerType],
278
- })
279
-
280
- const portableTextMemberSchemaTypesFromSanitySchema =
281
- createPortableTextMemberSchemaTypes(sanitySchema.get('body'))
282
-
283
- const portableTextSchema = sanitySchemaToPortableTextSchema(
284
- sanitySchema.get('body'),
285
- )
286
- const portableTextMemberSchemaTypesFromPortableTextSchema =
287
- compileSchemaDefinitionToPortableTextMemberSchemaTypes(portableTextSchema)
288
-
289
- expect(
290
- portableTextMemberSchemaTypesToSchema(
291
- portableTextMemberSchemaTypesFromPortableTextSchema,
292
- ),
293
- ).toEqual(
294
- portableTextMemberSchemaTypesToSchema(
295
- portableTextMemberSchemaTypesFromSanitySchema,
296
- ),
297
- )
298
- })
299
- })
@@ -1,48 +0,0 @@
1
- import type {Schema} from '@portabletext/schema'
2
- import {Schema as SanitySchema} from '@sanity/schema'
3
- import {builtinTypes} from '@sanity/schema/_internal'
4
- import type {ArrayDefinition, ArraySchemaType} from '@sanity/types'
5
- import {createPortableTextMemberSchemaTypes} from './portable-text-member-schema-types'
6
- import {portableTextMemberSchemaTypesToSchema} from './portable-text-member-schema-types-to-schema'
7
-
8
- /**
9
- * @public
10
- * Compile a Sanity schema to a Portable Text `Schema`.
11
- *
12
- * A Portable Text `Schema` is compatible with a Portable Text
13
- * `SchemaDefinition` and can be used as configuration for the Portable Text
14
- * Editor.
15
- *
16
- * @example
17
- * ```tsx
18
- * const schema = sanitySchemaToPortableTextSchema(sanitySchema)
19
- *
20
- * return (
21
- * <EditorProvider
22
- * initialConfig={{
23
- * // ...
24
- * schemaDefinition: schema,
25
- * }}
26
- * >
27
- * // ...
28
- * </EditorProvider>
29
- * ```
30
- */
31
- export function sanitySchemaToPortableTextSchema(
32
- sanitySchema: ArraySchemaType<unknown> | ArrayDefinition,
33
- ): Schema {
34
- const portableTextMemberSchemaTypes = createPortableTextMemberSchemaTypes(
35
- sanitySchema.hasOwnProperty('jsonType')
36
- ? sanitySchema
37
- : compileType(sanitySchema),
38
- )
39
-
40
- return portableTextMemberSchemaTypesToSchema(portableTextMemberSchemaTypes)
41
- }
42
-
43
- function compileType(rawType: any) {
44
- return SanitySchema.compile({
45
- name: 'blockTypeSchema',
46
- types: [rawType, ...builtinTypes],
47
- }).get(rawType.name)
48
- }
@@ -1,383 +0,0 @@
1
- import type {Schema} from '@portabletext/schema'
2
- import {describe, expect, test} from 'vitest'
3
- import {portableTextMemberSchemaTypesToSchema} from './portable-text-member-schema-types-to-schema'
4
- import {compileSchemaDefinitionToPortableTextMemberSchemaTypes} from './schema-definition-to-portable-text-member-schema-types'
5
-
6
- describe(compileSchemaDefinitionToPortableTextMemberSchemaTypes.name, () => {
7
- test("image object doesn't get Sanity-specific fields", () => {
8
- expect(
9
- compileSchemaDefinitionToPortableTextMemberSchemaTypes({
10
- blockObjects: [{name: 'image'}],
11
- }).blockObjects,
12
- ).toMatchObject([
13
- {
14
- name: 'image',
15
- fields: [],
16
- },
17
- ])
18
-
19
- expect(
20
- compileSchemaDefinitionToPortableTextMemberSchemaTypes({
21
- blockObjects: [
22
- {name: 'image', fields: [{name: 'src', type: 'string'}]},
23
- ],
24
- }).blockObjects,
25
- ).toMatchObject([
26
- {
27
- name: 'image',
28
- fields: [
29
- {
30
- name: 'src',
31
- type: {
32
- jsonType: 'string',
33
- },
34
- },
35
- ],
36
- },
37
- ])
38
- })
39
-
40
- test('back and forth test', () => {
41
- const schema: Schema = {
42
- annotations: [
43
- {
44
- name: 'link',
45
- fields: [
46
- {
47
- name: 'href',
48
- type: 'string',
49
- title: 'URL',
50
- },
51
- ],
52
- title: 'Link',
53
- },
54
- {
55
- name: 'canvasComment',
56
- fields: [
57
- {
58
- name: 'commentId',
59
- type: 'string',
60
- title: 'Comment ID',
61
- },
62
- ],
63
- title: 'Comment',
64
- },
65
- {
66
- name: 'canvasMapping',
67
- fields: [
68
- {
69
- name: 'documentPath',
70
- type: 'string',
71
- title: 'Document path',
72
- },
73
- {
74
- name: 'typePath',
75
- type: 'string',
76
- title: 'Type path',
77
- },
78
- {
79
- name: 'locked',
80
- type: 'boolean',
81
- title: 'Locked',
82
- },
83
- ],
84
- title: 'Mapping',
85
- },
86
- ],
87
- block: {
88
- name: 'block',
89
- },
90
- blockObjects: [
91
- {
92
- name: 'canvasDivider',
93
- fields: [
94
- {
95
- name: 'orientation',
96
- type: 'string',
97
- title: 'Orientation',
98
- },
99
- ],
100
- title: 'Divider',
101
- },
102
- {
103
- name: 'canvasFile',
104
- fields: [
105
- {
106
- name: 'asset',
107
- type: 'object',
108
- title: 'Asset',
109
- },
110
- {
111
- name: 'media',
112
- type: 'object',
113
- title: 'Media',
114
- },
115
- {
116
- name: 'title',
117
- type: 'string',
118
- title: 'Title',
119
- },
120
- {
121
- name: 'filename',
122
- type: 'string',
123
- title: 'Filename',
124
- },
125
- {
126
- name: 'type',
127
- type: 'string',
128
- title: 'Type',
129
- },
130
- {
131
- name: 'summary',
132
- type: 'string',
133
- title: 'Summary',
134
- },
135
- {
136
- name: 'large',
137
- type: 'boolean',
138
- title: 'Large',
139
- },
140
- ],
141
- title: 'File',
142
- },
143
- {
144
- name: 'canvasImage',
145
- fields: [
146
- {
147
- name: 'asset',
148
- type: 'object',
149
- title: 'Asset',
150
- },
151
- {
152
- name: 'media',
153
- type: 'object',
154
- title: 'Media',
155
- },
156
- {
157
- name: 'hotspot',
158
- type: 'object',
159
- title: 'Hotspot',
160
- },
161
- {
162
- name: 'crop',
163
- type: 'object',
164
- title: 'Crop',
165
- },
166
- {
167
- name: 'title',
168
- type: 'string',
169
- title: 'Title',
170
- },
171
- {
172
- name: 'alt',
173
- type: 'string',
174
- title: 'Alt',
175
- },
176
- {
177
- name: 'imageDimensions',
178
- type: 'object',
179
- title: 'Image Dimensions',
180
- },
181
- {
182
- name: 'sourceImageId',
183
- type: 'string',
184
- title: 'Source Image Id',
185
- },
186
- ],
187
- title: 'Image',
188
- },
189
- {
190
- name: 'canvasUrlBlock',
191
- fields: [
192
- {
193
- name: 'url',
194
- type: 'string',
195
- title: 'Url',
196
- },
197
- {
198
- name: 'title',
199
- type: 'string',
200
- title: 'Title',
201
- },
202
- {
203
- name: 'favicon',
204
- type: 'string',
205
- title: 'Favicon',
206
- },
207
- {
208
- name: 'description',
209
- type: 'string',
210
- title: 'Description',
211
- },
212
- {
213
- name: 'content',
214
- type: 'array',
215
- title: 'Content',
216
- },
217
- {
218
- name: 'error',
219
- type: 'string',
220
- title: 'Error',
221
- },
222
- ],
223
- title: 'Url block',
224
- },
225
- {
226
- name: 'canvasAiTask',
227
- fields: [
228
- {
229
- name: 'instruction',
230
- type: 'string',
231
- title: 'Instruction',
232
- },
233
- {
234
- name: 'input',
235
- type: 'array',
236
- title: 'Input',
237
- },
238
- ],
239
- title: 'AI task',
240
- },
241
- {
242
- name: 'canvasCode',
243
- fields: [
244
- {
245
- name: 'language',
246
- type: 'string',
247
- title: 'Language',
248
- },
249
- {
250
- name: 'code',
251
- type: 'array',
252
- title: 'Code',
253
- },
254
- {
255
- name: 'suggestions',
256
- type: 'object',
257
- title: 'Suggestions',
258
- },
259
- ],
260
- title: 'Code',
261
- },
262
- {
263
- name: 'canvasGlobalRef',
264
- fields: [
265
- {
266
- name: 'target',
267
- type: 'object',
268
- title: 'Target',
269
- },
270
- ],
271
- title: 'Reference for mapping',
272
- },
273
- {
274
- name: 'canvasPlaceholder',
275
- fields: [
276
- {
277
- name: 'title',
278
- type: 'string',
279
- title: 'Title',
280
- },
281
- {
282
- name: 'data',
283
- type: 'string',
284
- title: 'Data',
285
- },
286
- {
287
- name: 'map',
288
- type: 'object',
289
- title: 'Map',
290
- },
291
- ],
292
- title: 'Placeholder block',
293
- },
294
- ],
295
- decorators: [
296
- {
297
- name: 'strong',
298
- title: 'Bold',
299
- value: 'strong',
300
- },
301
- {
302
- name: 'em',
303
- title: 'Italic',
304
- value: 'em',
305
- },
306
- {
307
- name: 'strike-through',
308
- title: 'Strike',
309
- value: 'strike-through',
310
- },
311
- {
312
- name: 'code',
313
- title: 'Code',
314
- value: 'code',
315
- },
316
- ],
317
- inlineObjects: [],
318
- span: {
319
- name: 'span',
320
- },
321
- styles: [
322
- {
323
- name: 'normal',
324
- title: 'Text',
325
- value: 'normal',
326
- },
327
- {
328
- name: 'h1',
329
- title: 'Heading 1',
330
- value: 'h1',
331
- },
332
- {
333
- name: 'h2',
334
- title: 'Heading 2',
335
- value: 'h2',
336
- },
337
- {
338
- name: 'h3',
339
- title: 'Heading 3',
340
- value: 'h3',
341
- },
342
- {
343
- name: 'h4',
344
- title: 'Heading 4',
345
- value: 'h4',
346
- },
347
- {
348
- name: 'h5',
349
- title: 'Heading 5',
350
- value: 'h5',
351
- },
352
- {
353
- name: 'h6',
354
- title: 'Heading 6',
355
- value: 'h6',
356
- },
357
- {
358
- name: 'blockquote',
359
- title: 'Blockquote',
360
- value: 'blockquote',
361
- },
362
- ],
363
- lists: [
364
- {
365
- name: 'number',
366
- title: 'Numbered list',
367
- value: 'number',
368
- },
369
- {
370
- name: 'bullet',
371
- title: 'Bulleted list',
372
- value: 'bullet',
373
- },
374
- ],
375
- }
376
-
377
- expect(
378
- portableTextMemberSchemaTypesToSchema(
379
- compileSchemaDefinitionToPortableTextMemberSchemaTypes(schema),
380
- ),
381
- ).toEqual(schema)
382
- })
383
- })
@@ -1,200 +0,0 @@
1
- import type {SchemaDefinition} from '@portabletext/schema'
2
- import {Schema as SanitySchema} from '@sanity/schema'
3
- import {
4
- defineField,
5
- defineType,
6
- isArraySchemaType,
7
- isObjectSchemaType,
8
- type ObjectSchemaType,
9
- } from '@sanity/types'
10
- import startCase from 'lodash.startcase'
11
- import {keyGenerator} from './key-generator'
12
- import {
13
- createPortableTextMemberSchemaTypes,
14
- type PortableTextMemberSchemaTypes,
15
- } from './portable-text-member-schema-types'
16
-
17
- const temporaryImageBlockObjectName = `tmp-${keyGenerator()}-image`
18
- const temporaryUrlBlockObjectName = `tmp-${keyGenerator()}-url`
19
- const temporaryImageInlineObjectName = `tmp-${keyGenerator()}-image`
20
- const temporaryUrlInlineObjectName = `tmp-${keyGenerator()}-url`
21
-
22
- const temporaryBlockObjectNames: Record<string, string> = {
23
- image: temporaryImageBlockObjectName,
24
- url: temporaryUrlBlockObjectName,
25
- }
26
-
27
- const temporaryInlineObjectNames: Record<string, string> = {
28
- image: temporaryImageInlineObjectName,
29
- url: temporaryUrlInlineObjectName,
30
- }
31
-
32
- const blockObjectNames: Record<string, string> = {
33
- [temporaryImageBlockObjectName]: 'image',
34
- [temporaryUrlBlockObjectName]: 'url',
35
- }
36
-
37
- const inlineObjectNames: Record<string, string> = {
38
- [temporaryImageInlineObjectName]: 'image',
39
- [temporaryUrlInlineObjectName]: 'url',
40
- }
41
-
42
- const defaultObjectTitles: Record<string, string> = {
43
- image: 'Image',
44
- url: 'URL',
45
- }
46
-
47
- /**
48
- * @public
49
- * Compile a Portable Text schema definition to Sanity-specific schema types for
50
- * Portable Text.
51
- */
52
- export function compileSchemaDefinitionToPortableTextMemberSchemaTypes(
53
- definition?: SchemaDefinition,
54
- ): PortableTextMemberSchemaTypes {
55
- const blockObjects =
56
- definition?.blockObjects?.map((blockObject) =>
57
- defineType({
58
- type: 'object',
59
- // Very naive way to work around `SanitySchema.compile` adding default
60
- // fields to objects with certain names.
61
- name: temporaryBlockObjectNames[blockObject.name] ?? blockObject.name,
62
- title:
63
- blockObject.title === undefined
64
- ? // This avoids the default title which is a title case of the object name
65
- defaultObjectTitles[blockObject.name]
66
- : blockObject.title,
67
- fields:
68
- blockObject.fields?.map((field) => ({
69
- name: field.name,
70
- type: field.type,
71
- title: field.title ?? startCase(field.name),
72
- })) ?? [],
73
- }),
74
- ) ?? []
75
-
76
- const inlineObjects =
77
- definition?.inlineObjects?.map((inlineObject) =>
78
- defineType({
79
- type: 'object',
80
- // Very naive way to work around `SanitySchema.compile` adding default
81
- // fields to objects with certain names.
82
- name:
83
- temporaryInlineObjectNames[inlineObject.name] ?? inlineObject.name,
84
-
85
- title:
86
- inlineObject.title === undefined
87
- ? // This avoids the default title which is a title case of the object name
88
- defaultObjectTitles[inlineObject.name]
89
- : inlineObject.title,
90
- fields:
91
- inlineObject.fields?.map((field) => ({
92
- name: field.name,
93
- type: field.type,
94
- title: field.title ?? startCase(field.name),
95
- })) ?? [],
96
- }),
97
- ) ?? []
98
-
99
- const portableTextSchema = defineField({
100
- type: 'array',
101
- name: 'portable-text',
102
- of: [
103
- ...blockObjects.map((blockObject) => ({type: blockObject.name})),
104
- {
105
- type: 'block',
106
- name: 'block',
107
- of: inlineObjects.map((inlineObject) => ({type: inlineObject.name})),
108
- marks: {
109
- decorators:
110
- definition?.decorators?.map((decorator) => ({
111
- title: decorator.title ?? startCase(decorator.name),
112
- value: decorator.name,
113
- })) ?? [],
114
- annotations:
115
- definition?.annotations?.map((annotation) => ({
116
- name: annotation.name,
117
- type: 'object',
118
- title: annotation.title,
119
- fields:
120
- annotation.fields?.map((field) => ({
121
- name: field.name,
122
- title: field.title ?? startCase(field.name),
123
- type: field.type,
124
- })) ?? [],
125
- })) ?? [],
126
- },
127
- lists:
128
- definition?.lists?.map((list) => ({
129
- value: list.name,
130
- title: list.title ?? startCase(list.name),
131
- })) ?? [],
132
- styles:
133
- definition?.styles?.map((style) => ({
134
- value: style.name,
135
- title: style.title ?? startCase(style.name),
136
- })) ?? [],
137
- },
138
- ],
139
- })
140
-
141
- const schema = SanitySchema.compile({
142
- types: [portableTextSchema, ...blockObjects, ...inlineObjects],
143
- }).get('portable-text')
144
-
145
- const pteSchema = createPortableTextMemberSchemaTypes(schema)
146
-
147
- return {
148
- ...pteSchema,
149
- portableText: {
150
- ...pteSchema.portableText,
151
- of: pteSchema.portableText.of.map((schemaType) => {
152
- if (!isObjectSchemaType(schemaType)) {
153
- return schemaType
154
- }
155
-
156
- const nameMapping = blockObjectNames[schemaType.name]
157
-
158
- schemaType.name = nameMapping ?? schemaType.name
159
-
160
- for (const field of schemaType.fields) {
161
- if (field.name !== 'children' || !isArraySchemaType(field.type)) {
162
- continue
163
- }
164
-
165
- for (const ofSchemaType of field.type.of) {
166
- const nameMapping = inlineObjectNames[ofSchemaType.name]
167
-
168
- if (!nameMapping) {
169
- continue
170
- }
171
-
172
- ofSchemaType.name = nameMapping
173
- }
174
- }
175
-
176
- return schemaType
177
- }),
178
- },
179
- blockObjects: pteSchema.blockObjects.map((blockObject) =>
180
- blockObjectNames[blockObject.name] !== undefined
181
- ? ({
182
- ...blockObject,
183
- name: blockObjectNames[blockObject.name],
184
- type: {
185
- ...blockObject.type,
186
- name: blockObjectNames[blockObject.name],
187
- },
188
- } as ObjectSchemaType)
189
- : blockObject,
190
- ),
191
- inlineObjects: pteSchema.inlineObjects.map((inlineObject) =>
192
- inlineObjectNames[inlineObject.name] !== undefined
193
- ? ({
194
- ...inlineObject,
195
- name: inlineObjectNames[inlineObject.name],
196
- } as ObjectSchemaType)
197
- : inlineObject,
198
- ),
199
- } satisfies PortableTextMemberSchemaTypes
200
- }