import type { Block } from "@prismicio/types-internal/lib/content" import { RichText, RichTextNodeType, } from "@prismicio/types-internal/lib/customtypes" import { LoremIpsum } from "lorem-ipsum" import type { MockConfig } from "../../../MockConfig" import { slug } from "../../../utils" export type RichTextMockPattern = keyof typeof Patterns const LoremDefaultConfig = { sentencesPerParagraph: { min: 1, max: 3, }, wordsPerSentence: { min: 4, max: 16, }, } as const export interface RichTextMockConfig extends MockConfig> { nbBlocks?: number pattern?: RichTextMockPattern } export const Patterns = { PARAGRAPH: { title: "Simple Paragraph", test: (options: ReadonlyArray) => options.some((e) => e === RichTextNodeType.paragraph), value: (): RichTextNodeType[] => [RichTextNodeType.paragraph], description: "A single paragraph with a variant number of words.", loremConfig: LoremDefaultConfig, }, HEADING: { title: "Section Title", test: (options: ReadonlyArray) => options.some(RichTextMockConfig.isHeading), value: (options: ReadonlyArray): RichTextNodeType[] => [ options.find(RichTextMockConfig.isHeading) || RichTextNodeType.heading1, ], description: "A single heading (h1 to h6) with a variant number of words.", loremConfig: LoremDefaultConfig, }, STORY: { title: "Story", test: (options: ReadonlyArray) => options.some(RichTextMockConfig.isHeading) && options.some((e) => e === RichTextNodeType.paragraph), value: (options: ReadonlyArray): RichTextNodeType[] => [ options.find(RichTextMockConfig.isHeading) || RichTextNodeType.heading1, ...RichTextMockConfig.optionalType(options, RichTextNodeType.image), RichTextNodeType.paragraph, ], description: "Content with headings, texts and optional images", loremConfig: LoremDefaultConfig, }, TABLE_HEADER: { title: "Table header", test: (options: ReadonlyArray) => options.some((e) => e === RichTextNodeType.paragraph), value: (): RichTextNodeType[] => [RichTextNodeType.paragraph], description: "A very short paragraph that can be used as a table header.", loremConfig: { sentencesPerParagraph: { min: 1, max: 1, }, wordsPerSentence: { min: 1, max: 2, }, }, }, TABLE_CELL: { title: "Table cell", test: (options: ReadonlyArray) => options.some((e) => e === RichTextNodeType.paragraph), value: (): RichTextNodeType[] => [RichTextNodeType.paragraph], description: "A single sentence paragraph that can be used as a table cell.", loremConfig: { sentencesPerParagraph: { min: 1, max: 1, }, wordsPerSentence: { min: 4, max: 8, }, }, }, } export const RichTextMockConfig = { INITIAL_CONFIG: { pattern: Patterns.PARAGRAPH, blocks: 1, }, isHeading: (type: string) => type.indexOf("heading") === 0, isText: (type: string) => type === RichTextNodeType.paragraph || RichTextMockConfig.isHeading(type), isImage: (type: string) => type === RichTextNodeType.image, optionalType: ( options: ReadonlyArray, type: RichTextNodeType, ) => (options.find((e) => e === type) && Math.random() > 0.5 ? [type] : []), findMatchingPattern: (options: ReadonlyArray) => { const PatternEntry = Object.entries(Patterns).find(([, patt]) => patt.test(options), ) if (PatternEntry && PatternEntry.length) { return PatternEntry[1] } return RichTextMockConfig.INITIAL_CONFIG.pattern }, generateText: ( contentType: string, loremConfig: { sentencesPerParagraph: { min: number; max: number } wordsPerSentence: { min: number; max: number } }, ): string => { if (RichTextMockConfig.isHeading(contentType)) { const fake = slug({ min: 5, max: 10 }) return [fake[0] && fake[0].toUpperCase(), ...fake.slice(1)].join("") } const lorem = new LoremIpsum(loremConfig) return lorem.generateParagraphs(1) }, }