Domain Entities: Unit 4 — Image & Media
ImageImportResult
The result of importing an image (via drag & drop or clipboard paste) into the document’s assets directory.
struct ImageImportResult {
let relativePath: String // e.g., "MyDoc.assets/screenshot-20260402-143012.png"
let format: ImageFormat
let fileSize: UInt64 // Bytes written
let dimensions: CGSize // Width x Height in pixels
}
ImageFormat
Supported image formats for import.
enum ImageFormat: String, CaseIterable {
case png = "png"
case jpeg = "jpeg"
case gif = "gif"
var utType: UTType {
switch self {
case .png: return .png
case .jpeg: return .jpeg
case .gif: return .gif
}
}
var fileExtension: String { rawValue }
/// Formats that can be read from a drag operation (file-based)
static let droppable: Set<ImageFormat> = [.png, .jpeg, .gif]
/// Formats that can be read from NSPasteboard (bitmap data)
static let pasteable: Set<ImageFormat> = [.png]
}
AssetReference
A validated reference to an image asset within the document’s assets directory.
struct AssetReference: Equatable {
let assetsDirectoryURL: URL // Absolute URL to {filename}.assets/
let filename: String // e.g., "screenshot-20260402-143012.png"
var relativeMarkdownPath: String {
// "{docname}.assets/{filename}" — relative to the .md file's parent
assetsDirectoryURL.lastPathComponent + "/" + filename
}
var absoluteURL: URL {
assetsDirectoryURL.appendingPathComponent(filename)
}
}
DragDropPayload
Encapsulates the data extracted from an NSDraggingInfo sender during a drop operation.
struct DragDropPayload {
let fileURLs: [URL] // File URLs from the pasteboard (filtered to supported image types)
let dropLocation: Int // Character offset in the text view where the drop occurred
}
PasteboardImageData
Encapsulates image data extracted from the system clipboard for paste operations.
struct PasteboardImageData {
let image: NSImage // The bitmap image from the pasteboard
let sourceFormat: ImageFormat // Always .png for pasteboard images (normalized)
let originalUTType: UTType? // The original UTType on the pasteboard, if available
}
ImageImportError
Errors that can occur during image import operations.
enum ImageImportError: LocalizedError {
case unsupportedFormat(String) // File extension not in ImageFormat
case documentNotSaved // Document has no file URL (untitled)
case assetsDirectoryCreationFailed(Error) // Could not create .assets/ directory
case fileWriteFailed(URL, Error) // Could not write image file
case pathValidationFailed(String) // Path violates SEC-01 rules
case imageDataConversionFailed // NSImage could not produce PNG data
case fileSizeExceeded(UInt64) // Image exceeds maximum allowed size
case pasteboardReadFailed // Could not read image from pasteboard
var errorDescription: String? {
switch self {
case .unsupportedFormat(let ext):
return "Unsupported image format: \(ext)"
case .documentNotSaved:
return "Please save the document before inserting images."
case .assetsDirectoryCreationFailed(let error):
return "Failed to create assets directory: \(error.localizedDescription)"
case .fileWriteFailed(let url, let error):
return "Failed to write image to \(url.lastPathComponent): \(error.localizedDescription)"
case .pathValidationFailed(let reason):
return "Invalid image path: \(reason)"
case .imageDataConversionFailed:
return "Failed to convert image to PNG format."
case .fileSizeExceeded(let size):
return "Image size (\(size) bytes) exceeds the maximum allowed."
case .pasteboardReadFailed:
return "No image data found on the clipboard."
}
}
}
ImageInsertionContext
Provides the context needed to insert a Markdown image reference into the source text.
struct ImageInsertionContext {
let position: Int // Character offset in source text
let relativePath: String // Validated relative path for Markdown reference
let altText: String // Alt text (derived from filename, sans extension)
var markdownSnippet: String {
")"
}
}