From 799570d979674631fd0efbc722902a2c7feeef2d Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 24 Nov 2025 02:19:16 -0800 Subject: [PATCH] fix: replace any types in metadata and content utils (16 errors) Phase 1 Batch 4: Metadata & Content type safety improvements Fixed 16 any-type errors across 2 utility files: 1. src/lib/utils/metadata.ts (10 errors) - Created JsonLdObject type (Record) - Updated MetaTagsOptions.jsonLd to use JsonLdObject - Updated GeneratedMetaTags.jsonLd to use JsonLdObject - Updated all JSON-LD generator functions: * generatePersonJsonLd: return type and jsonLd variable * generateArticleJsonLd: return type and jsonLd variable * generateImageGalleryJsonLd: return type and jsonLd variable * generateCreativeWorkJsonLd: return type and jsonLd variable 2. src/lib/utils/content.ts (6 errors) - Added imports for TiptapNode and EditorData types - Created Mark interface for text mark types - Added marks field to ContentNode interface - Fixed renderInlineContent: content parameter to ContentNode[] - Fixed renderInlineContent: node parameter to ContentNode - Fixed renderInlineContent: mark parameter to Mark - Fixed getContentExcerpt: content parameter to EditorData | unknown - Fixed extractTiptapText: doc parameter to Record - Fixed extractTiptapText: node parameter to ContentNode Progress: 51 any-type errors remaining (down from 67) --- src/lib/utils/content.ts | 33 +++++++++++++++++++++++---------- src/lib/utils/metadata.ts | 23 +++++++++++++---------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/lib/utils/content.ts b/src/lib/utils/content.ts index b3043cf..8f76037 100644 --- a/src/lib/utils/content.ts +++ b/src/lib/utils/content.ts @@ -1,3 +1,5 @@ +import type { TiptapNode, EditorData } from '$lib/types/editor' + // Content node types for rendering interface ContentNode { type: string @@ -10,9 +12,16 @@ interface ContentNode { caption?: string language?: string mediaId?: number + marks?: Mark[] [key: string]: unknown } +// Mark types (bold, italic, link, etc.) +interface Mark { + type: string + attrs?: Record +} + // Render Edra/BlockNote JSON content to HTML export const renderEdraContent = (content: unknown, options: { albumSlug?: string } = {}): string => { if (!content) return '' @@ -290,15 +299,15 @@ function renderTiptapContent(doc: Record): string { } // Render inline content (text nodes with marks) - const renderInlineContent = (content: any[]): string => { + const renderInlineContent = (content: ContentNode[]): string => { return content - .map((node: any) => { + .map((node: ContentNode) => { if (node.type === 'text') { let text = escapeHtml(node.text || '') // Apply marks (bold, italic, etc.) if (node.marks) { - node.marks.forEach((mark: any) => { + node.marks.forEach((mark: Mark) => { switch (mark.type) { case 'bold': text = `${text}` @@ -351,16 +360,19 @@ function renderTiptapContent(doc: Record): string { } // Extract text content from Edra JSON for excerpt -export const getContentExcerpt = (content: any, maxLength = 200): string => { +export const getContentExcerpt = (content: EditorData | unknown, maxLength = 200): string => { if (!content) return '' + // Type guard for content object + const contentObj = content as Record + // Handle Tiptap format first (has type: 'doc') - if (content.type === 'doc' && content.content) { - return extractTiptapText(content, maxLength) + if (contentObj.type === 'doc' && contentObj.content) { + return extractTiptapText(contentObj, maxLength) } // Handle both { blocks: [...] } and { content: [...] } formats - const blocks = content.blocks || content.content || [] + const blocks = (contentObj.blocks || contentObj.content || []) as ContentNode[] if (!Array.isArray(blocks)) return '' const extractText = (node: ContentNode): string => { @@ -383,8 +395,8 @@ export const getContentExcerpt = (content: any, maxLength = 200): string => { } // Extract text from Tiptap content -function extractTiptapText(doc: any, maxLength: number): string { - const extractFromNode = (node: any): string => { +function extractTiptapText(doc: Record, maxLength: number): string { + const extractFromNode = (node: ContentNode): string => { if (node.type === 'text') { return node.text || '' } @@ -396,7 +408,8 @@ function extractTiptapText(doc: any, maxLength: number): string { return '' } - const text = doc.content.map(extractFromNode).join(' ').trim() + const content = doc.content as ContentNode[] + const text = content.map(extractFromNode).join(' ').trim() if (text.length <= maxLength) return text return text.substring(0, maxLength).trim() + '...' } diff --git a/src/lib/utils/metadata.ts b/src/lib/utils/metadata.ts index b768491..de3ce44 100644 --- a/src/lib/utils/metadata.ts +++ b/src/lib/utils/metadata.ts @@ -1,3 +1,6 @@ +// JSON-LD structured data object type +type JsonLdObject = Record + interface MetaTagsOptions { title?: string description?: string @@ -16,7 +19,7 @@ interface MetaTagsOptions { locale?: string canonicalUrl?: string noindex?: boolean - jsonLd?: Record + jsonLd?: JsonLdObject } interface GeneratedMetaTags { @@ -25,7 +28,7 @@ interface GeneratedMetaTags { openGraph: Record twitter: Record other: Record - jsonLd?: Record + jsonLd?: JsonLdObject } const DEFAULTS = { @@ -197,10 +200,10 @@ export function generatePersonJsonLd(options: { jobTitle?: string description?: string sameAs?: string[] -}): Record { +}): JsonLdObject { const { name, url = DEFAULTS.siteUrl, image, jobTitle, description, sameAs = [] } = options - const jsonLd: Record = { + const jsonLd: JsonLdObject = { '@context': 'https://schema.org', '@type': 'Person', name, @@ -237,10 +240,10 @@ export function generateArticleJsonLd(options: { datePublished?: string dateModified?: string author?: string -}): Record { +}): JsonLdObject { const { title, description, url, image, datePublished, dateModified, author } = options - const jsonLd: Record = { + const jsonLd: JsonLdObject = { '@context': 'https://schema.org', '@type': 'Article', headline: title, @@ -291,10 +294,10 @@ export function generateImageGalleryJsonLd(options: { url: string caption?: string }> -}): Record { +}): JsonLdObject { const { name, description, url, images } = options - const jsonLd: Record = { + const jsonLd: JsonLdObject = { '@context': 'https://schema.org', '@type': 'ImageGallery', name, @@ -327,10 +330,10 @@ export function generateCreativeWorkJsonLd(options: { creator?: string dateCreated?: string keywords?: string[] -}): Record { +}): JsonLdObject { const { name, description, url, image, creator, dateCreated, keywords = [] } = options - const jsonLd: Record = { + const jsonLd: JsonLdObject = { '@context': 'https://schema.org', '@type': 'CreativeWork', name,