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<string, unknown>)
   - 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<string, unknown>
   - Fixed extractTiptapText: node parameter to ContentNode

Progress: 51 any-type errors remaining (down from 67)
This commit is contained in:
Justin Edmund 2025-11-24 02:19:16 -08:00
parent f31d02d51c
commit 799570d979
2 changed files with 36 additions and 20 deletions

View file

@ -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<string, unknown>
}
// 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, unknown>): 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 = `<strong>${text}</strong>`
@ -351,16 +360,19 @@ function renderTiptapContent(doc: Record<string, unknown>): 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<string, unknown>
// 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<string, unknown>, 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() + '...'
}

View file

@ -1,3 +1,6 @@
// JSON-LD structured data object type
type JsonLdObject = Record<string, unknown>
interface MetaTagsOptions {
title?: string
description?: string
@ -16,7 +19,7 @@ interface MetaTagsOptions {
locale?: string
canonicalUrl?: string
noindex?: boolean
jsonLd?: Record<string, any>
jsonLd?: JsonLdObject
}
interface GeneratedMetaTags {
@ -25,7 +28,7 @@ interface GeneratedMetaTags {
openGraph: Record<string, string>
twitter: Record<string, string>
other: Record<string, string>
jsonLd?: Record<string, any>
jsonLd?: JsonLdObject
}
const DEFAULTS = {
@ -197,10 +200,10 @@ export function generatePersonJsonLd(options: {
jobTitle?: string
description?: string
sameAs?: string[]
}): Record<string, any> {
}): JsonLdObject {
const { name, url = DEFAULTS.siteUrl, image, jobTitle, description, sameAs = [] } = options
const jsonLd: Record<string, any> = {
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<string, any> {
}): JsonLdObject {
const { title, description, url, image, datePublished, dateModified, author } = options
const jsonLd: Record<string, any> = {
const jsonLd: JsonLdObject = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: title,
@ -291,10 +294,10 @@ export function generateImageGalleryJsonLd(options: {
url: string
caption?: string
}>
}): Record<string, any> {
}): JsonLdObject {
const { name, description, url, images } = options
const jsonLd: Record<string, any> = {
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<string, any> {
}): JsonLdObject {
const { name, description, url, image, creator, dateCreated, keywords = [] } = options
const jsonLd: Record<string, any> = {
const jsonLd: JsonLdObject = {
'@context': 'https://schema.org',
'@type': 'CreativeWork',
name,