- replace any with Prisma types (Post, Project, Album, Media) - use Component type for Svelte component parameters - use Snippet type for Svelte 5 render slots - use Record<string, unknown> for dynamic objects - add proper type guards for error handling - fix editor extension types with proper generics - all frontend components now have zero any type errors
129 lines
5.3 KiB
TypeScript
129 lines
5.3 KiB
TypeScript
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight'
|
|
import { all, createLowlight } from 'lowlight'
|
|
import { SvelteNodeViewRenderer } from 'svelte-tiptap'
|
|
import type { Extensions } from '@tiptap/core'
|
|
|
|
// Extension classes
|
|
import { AudioPlaceholder } from './extensions/audio/AudioPlaceholder.js'
|
|
import { ImagePlaceholder } from './extensions/image/ImagePlaceholder.js'
|
|
import { VideoPlaceholder } from './extensions/video/VideoPlaceholder.js'
|
|
import { AudioExtended } from './extensions/audio/AudiExtended.js'
|
|
import { ImageExtended } from './extensions/image/ImageExtended.js'
|
|
import { VideoExtended } from './extensions/video/VideoExtended.js'
|
|
import { GalleryPlaceholder } from './extensions/gallery/GalleryPlaceholder.js'
|
|
import { GalleryExtended } from './extensions/gallery/GalleryExtended.js'
|
|
import { IFramePlaceholder } from './extensions/iframe/IFramePlaceholder.js'
|
|
import { IFrameExtended } from './extensions/iframe/IFrameExtended.js'
|
|
import { UrlEmbed } from './extensions/url-embed/UrlEmbed.js'
|
|
import { UrlEmbedPlaceholder } from './extensions/url-embed/UrlEmbedPlaceholder.js'
|
|
import { UrlEmbedExtended } from './extensions/url-embed/UrlEmbedExtended.js'
|
|
import { LinkContextMenu } from './extensions/link-context-menu/LinkContextMenu.js'
|
|
import { GeolocationPlaceholder } from './extensions/geolocation/GeolocationPlaceholder.js'
|
|
import { GeolocationExtended } from './extensions/geolocation/GeolocationExtended.js'
|
|
import slashcommand from './extensions/slash-command/slashcommand.js'
|
|
|
|
// Component imports
|
|
import CodeExtended from './headless/components/CodeExtended.svelte'
|
|
import AudioPlaceholderComponent from './headless/components/AudioPlaceholder.svelte'
|
|
import AudioExtendedComponent from './headless/components/AudioExtended.svelte'
|
|
import ImagePlaceholderComponent from './headless/components/ImagePlaceholder.svelte'
|
|
import ImageExtendedComponent from './headless/components/ImageExtended.svelte'
|
|
import VideoPlaceholderComponent from './headless/components/VideoPlaceholder.svelte'
|
|
import VideoExtendedComponent from './headless/components/VideoExtended.svelte'
|
|
import GalleryPlaceholderComponent from './headless/components/GalleryPlaceholder.svelte'
|
|
import GalleryExtendedComponent from './headless/components/GalleryExtended.svelte'
|
|
import IFramePlaceholderComponent from './headless/components/IFramePlaceholder.svelte'
|
|
import IFrameExtendedComponent from './headless/components/IFrameExtended.svelte'
|
|
import UrlEmbedPlaceholderComponent from './headless/components/UrlEmbedPlaceholder.svelte'
|
|
import UrlEmbedExtendedComponent from './headless/components/UrlEmbedExtended.svelte'
|
|
import GeolocationPlaceholderComponent from './headless/components/GeolocationPlaceholder.svelte'
|
|
import GeolocationExtendedComponent from './headless/components/GeolocationExtended.svelte'
|
|
import SlashCommandList from './headless/components/SlashCommandList.svelte'
|
|
|
|
// Create lowlight instance
|
|
const lowlight = createLowlight(all)
|
|
|
|
import type { Component } from 'svelte'
|
|
|
|
export interface EditorExtensionOptions {
|
|
showSlashCommands?: boolean
|
|
onShowUrlConvertDropdown?: (pos: number, url: string) => void
|
|
onShowLinkContextMenu?: (pos: number, url: string, coords: { x: number; y: number }) => void
|
|
imagePlaceholderComponent?: Component // Allow custom image placeholder component
|
|
}
|
|
|
|
export function getEditorExtensions(options: EditorExtensionOptions = {}): Extensions {
|
|
const {
|
|
showSlashCommands = true,
|
|
onShowUrlConvertDropdown,
|
|
onShowLinkContextMenu,
|
|
imagePlaceholderComponent = ImagePlaceholderComponent
|
|
} = options
|
|
|
|
const extensions: Extensions = [
|
|
CodeBlockLowlight.configure({
|
|
lowlight
|
|
}).extend({
|
|
addNodeView() {
|
|
return SvelteNodeViewRenderer(CodeExtended)
|
|
}
|
|
}),
|
|
AudioPlaceholder(AudioPlaceholderComponent),
|
|
ImagePlaceholder(imagePlaceholderComponent),
|
|
VideoPlaceholder(VideoPlaceholderComponent),
|
|
AudioExtended(AudioExtendedComponent),
|
|
ImageExtended(ImageExtendedComponent),
|
|
VideoExtended(VideoExtendedComponent),
|
|
GalleryPlaceholder(GalleryPlaceholderComponent),
|
|
GalleryExtended(GalleryExtendedComponent),
|
|
IFramePlaceholder(IFramePlaceholderComponent),
|
|
IFrameExtended(IFrameExtendedComponent),
|
|
GeolocationPlaceholder(GeolocationPlaceholderComponent),
|
|
GeolocationExtended(GeolocationExtendedComponent)
|
|
]
|
|
|
|
// Add URL embed extensions with callbacks if provided
|
|
if (onShowUrlConvertDropdown) {
|
|
extensions.push(
|
|
UrlEmbed.configure({ onShowDropdown: onShowUrlConvertDropdown }),
|
|
UrlEmbedPlaceholder(UrlEmbedPlaceholderComponent),
|
|
UrlEmbedExtended(UrlEmbedExtendedComponent)
|
|
)
|
|
} else {
|
|
extensions.push(
|
|
UrlEmbed,
|
|
UrlEmbedPlaceholder(UrlEmbedPlaceholderComponent),
|
|
UrlEmbedExtended(UrlEmbedExtendedComponent)
|
|
)
|
|
}
|
|
|
|
// Add link context menu if callback provided
|
|
if (onShowLinkContextMenu) {
|
|
extensions.push(LinkContextMenu.configure({ onShowContextMenu: onShowLinkContextMenu }))
|
|
} else {
|
|
extensions.push(LinkContextMenu)
|
|
}
|
|
|
|
// Add slash commands if enabled
|
|
if (showSlashCommands) {
|
|
extensions.push(slashcommand(SlashCommandList))
|
|
}
|
|
|
|
return extensions
|
|
}
|
|
|
|
// Extension presets for different editor variants
|
|
export const EDITOR_PRESETS = {
|
|
full: {
|
|
showSlashCommands: true,
|
|
includeAllExtensions: true
|
|
},
|
|
inline: {
|
|
showSlashCommands: true,
|
|
includeAllExtensions: true
|
|
},
|
|
minimal: {
|
|
showSlashCommands: false,
|
|
includeAllExtensions: false
|
|
}
|
|
}
|