Files
bookhoard/internal/sync/format.go
T
John O'Keefe 72839921f2 drop DOC and LIT from the pipeline (deliberately unsupported)
.IMAGE  — extensions removed from AllowedExtensions (scan gate),
bookExtensions, MimeTypes and sync/format.go maps: .doc/.lit files
are no longer scanned or indexed. classifyFormatGroup gains the
RTF and PDB reflowable arms that were missing when those rungs
shipped (rows only reclassify on creation). Scanner docs updated.

DOC + LIT have no credible JS tooling (mammoth is docx-only; LIT
needs LZX and its DRM variants are dead) and text-extraction-only
support would misrepresent what the reader can do. Verified: probe
.doc/.lit files watched but never scanned; probe .txt control
scanned; TestClassifyFormatGroup extended and passing.

Docs change granted in-session by the user (extensions + format
docs).
2026-10-03 16:11:04 -04:00

129 lines
3.1 KiB
Go

package sync
import (
"path/filepath"
"strings"
)
// FormatGroup represents the three main format categories
type FormatGroup string
const (
FormatGroupReflowable FormatGroup = "reflowable"
FormatGroupFixedLayout FormatGroup = "fixed_layout"
FormatGroupComicArchive FormatGroup = "comic_archive"
FormatGroupUnknown FormatGroup = "unknown"
)
// MimeType mappings for common ebook formats
var mimeTypes = map[string]string{
".epub": "application/epub+zip",
".mobi": "application/x-mobipocket-ebook",
".azw": "application/x-mobipocket-ebook",
".azw3": "application/vnd.amazon.mobi8-ebook",
".pdf": "application/pdf",
".djvu": "image/vnd.djvu",
".cbz": "application/x-cbz",
".cbr": "application/x-cbr",
".cb7": "application/x-cb7",
".cbt": "application/x-cbt",
".fb2": "application/x-fictionbook+xml",
".txt": "text/plain",
".rtf": "application/rtf",
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".pdb": "application/vnd.palm",
".prc": "application/vnd.palm",
}
// ReflowableFormats are formats that support text reflow
var ReflowableFormats = map[string]bool{
".epub": true,
".mobi": true,
".azw": true,
".azw3": true,
".fb2": true,
".txt": true,
".rtf": true,
".docx": true,
".pdb": true,
".prc": true,
}
// FixedLayoutFormats are formats with fixed page layouts
var FixedLayoutFormats = map[string]bool{
".pdf": true,
".djvu": true,
}
// ComicArchiveFormats are comic archive formats
var ComicArchiveFormats = map[string]bool{
".cbz": true,
".cbr": true,
".cb7": true,
".cbt": true,
}
// DetectFormatGroup determines the format group based on mimetype and file path
func DetectFormatGroup(mimetype string, filePath string) FormatGroup {
ext := strings.ToLower(filepath.Ext(filePath))
// Check by mimetype first
switch mimetype {
case "application/epub+zip",
"application/x-mobipocket-ebook",
"application/vnd.amazon.mobi8-ebook",
"application/x-fictionbook+xml",
"text/plain":
return FormatGroupReflowable
case "application/pdf",
"image/vnd.djvu":
return FormatGroupFixedLayout
case "application/x-cbr",
"application/x-cbz",
"application/x-cb7",
"application/x-cbt":
return FormatGroupComicArchive
}
// Fall back to file extension
if ReflowableFormats[ext] {
return FormatGroupReflowable
}
if FixedLayoutFormats[ext] {
return FormatGroupFixedLayout
}
if ComicArchiveFormats[ext] {
return FormatGroupComicArchive
}
return FormatGroupUnknown
}
// GetMimeType returns the mimetype for a given file extension
func GetMimeType(filePath string) string {
ext := strings.ToLower(filepath.Ext(filePath))
if mt, ok := mimeTypes[ext]; ok {
return mt
}
return ""
}
// IsReflowable checks if a format is reflowable
func IsReflowable(formatGroup FormatGroup) bool {
return formatGroup == FormatGroupReflowable
}
// HasFixedLayout checks if a format has fixed layout
func HasFixedLayout(formatGroup FormatGroup) bool {
return formatGroup == FormatGroupFixedLayout
}
// IsComicArchive checks if a format is a comic archive
func IsComicArchive(formatGroup FormatGroup) bool {
return formatGroup == FormatGroupComicArchive
}