Documentation
¶
Overview ¶
Package extract is the framework-free document/content extraction library. It imports nothing from the monolith — no Gin, no GORM, no internal/config — so it can be linked into the sandboxed tmi-extractor worker and into the monolith's api package alike.
This package holds the foundation types relocated from package api during TMI Component Platform Plan 2 (issue #347): the extractor interfaces (ContentExtractor, ContextAwareExtractor, BoundedExtractor), the extraction result and entity-reference types, the sentinel errors and reason-code constants, the typed-error classifier (ClassifyError), and the extraction Limits struct with DefaultLimits. The extractor registry and the OOXML/PDF/HTML/plaintext extractors were relocated here by Plan 2 Task 6.
The move is a relocation, not a rewrite: the extraction logic is byte-for-byte the same; only the package boundary, the import paths, and the exported-identifier surface changed.
Index ¶
- Constants
- Variables
- func ExtractTextFromHTML(htmlContent string) string
- func NewLimitError(kind, detail string) error
- type BoundedExtractor
- type Classification
- type ContentExtractor
- type ContentExtractorRegistry
- type ContextAwareExtractor
- type DOCXExtractor
- func (e *DOCXExtractor) Bounded() bool
- func (e *DOCXExtractor) CanHandle(contentType string) bool
- func (e *DOCXExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
- func (e *DOCXExtractor) ExtractCtx(ctx context.Context, data []byte, contentType string) (ExtractedContent, error)
- func (e *DOCXExtractor) Name() string
- type EntityReference
- type ExtractedContent
- type HTMLExtractor
- type Limits
- type PDFExtractor
- type PPTXExtractor
- func (e *PPTXExtractor) Bounded() bool
- func (e *PPTXExtractor) CanHandle(contentType string) bool
- func (e *PPTXExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
- func (e *PPTXExtractor) ExtractCtx(ctx context.Context, data []byte, contentType string) (ExtractedContent, error)
- func (e *PPTXExtractor) Name() string
- type PlainTextExtractor
- type TextChunker
- type XLSXExtractor
- func (e *XLSXExtractor) Bounded() bool
- func (e *XLSXExtractor) CanHandle(contentType string) bool
- func (e *XLSXExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
- func (e *XLSXExtractor) ExtractCtx(ctx context.Context, data []byte, contentType string) (ExtractedContent, error)
- func (e *XLSXExtractor) Name() string
Constants ¶
const ( ReasonExtractionLimitCompressedSize = "extraction_limit:compressed_size" ReasonExtractionLimitDecompressedSize = "extraction_limit:decompressed_size" ReasonExtractionLimitPartSize = "extraction_limit:part_size" ReasonExtractionLimitPartCount = "extraction_limit:part_count" ReasonExtractionLimitMarkdownSize = "extraction_limit:markdown_size" ReasonExtractionLimitTimeout = "extraction_limit:timeout" ReasonExtractionLimitXMLDepth = "extraction_limit:xml_depth" ReasonExtractionLimitZipNested = "extraction_limit:zip_nested" ReasonExtractionLimitZipPath = "extraction_limit:zip_path" ReasonExtractionLimitCompressionRatio = "extraction_limit:compression_ratio" ReasonExtractionMalformed = "extraction_malformed" ReasonExtractionUnsupported = "extraction_unsupported" ReasonExtractionInternal = "extraction_internal" )
Extraction access-reason-code constants. Relocated verbatim from api/access_diagnostics.go so the monolith and the worker agree on the strings written to access_reason_code / the result envelope.
Variables ¶
var ( ErrExtractionLimit = errors.New("extraction limit exceeded") ErrMalformed = errors.New("malformed document") ErrUnsupported = errors.New("unsupported document subformat") )
Sentinel errors returned by extractors. Callers use errors.Is to classify.
Functions ¶
func ExtractTextFromHTML ¶
ExtractTextFromHTML parses an HTML document and returns the concatenated visible text, skipping content inside <script> and <style> elements. This is the single source of truth shared by the HTMLExtractor and the api HTTP content provider. SEM@d056a3ea026249d40d05ab6af7f092a043f72c7a: parse an HTML document and concatenate visible text, skipping script and style subtrees (pure)
func NewLimitError ¶
NewLimitError builds a typed extraction-limit error for the given Kind (one of the documented Kind values: compressed_size, decompressed_size, part_size, part_count, markdown_size, xml_depth, zip_nested, zip_path, compression_ratio) with an optional human-readable detail. The result satisfies errors.Is(err, ErrExtractionLimit) and is classified by ClassifyError into the matching reason code.
The extractors themselves construct the package-private value directly; this constructor exists so callers outside the package (e.g. the monolith's pipeline/poller tests) can inject a classifiable limit error without depending on the private type.
Limit and Observed are left zero — this constructor is for classification and test injection, not for producing human-facing limit diagnostics. SEM@d1fd850907490887fd11a6ccd4a691326ede6e4e: build a classifiable extraction-limit error for a given kind and detail (pure)
Types ¶
type BoundedExtractor ¶
type BoundedExtractor interface {
Bounded() bool
}
BoundedExtractor is implemented by extractors that must run under a wall-clock deadline (CPU- or memory-heavy extractors that could otherwise run indefinitely on adversarial input). The pipeline calls Bounded() to detect the requirement; the value is informational and always true for types that implement it. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: interface marking extractors that require a wall-clock deadline for safety (pure)
type Classification ¶
Classification describes how a typed extractor error maps to a reason code, plus an optional human-readable Detail. Relocated from api.ExtractionClassification; the Status field is dropped because access_status is a monolith concept — the worker reports only reason codes, and the monolith's result-consumer (Plan 3) derives access_status. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: pair a reason code with an optional human-readable detail for an extraction error (pure)
func ClassifyError ¶
func ClassifyError(err error) Classification
ClassifyError walks the error chain and returns the matching reason code. Default is ReasonExtractionInternal. A nil error returns the zero value. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: walk an error chain and return the matching extraction reason code (pure)
type ContentExtractor ¶
type ContentExtractor interface {
Name() string
CanHandle(contentType string) bool
Extract(data []byte, contentType string) (ExtractedContent, error)
}
ContentExtractor converts raw bytes into plain text. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: interface for converting raw bytes of a known content type into extracted text (pure)
type ContentExtractorRegistry ¶
type ContentExtractorRegistry struct {
// contains filtered or unexported fields
}
ContentExtractorRegistry manages content extractors in priority order. SEM@b4a403da2147ccb51a674e10d71891d4fccfe06a: ordered registry of content extractors matched by content type (pure)
func NewContentExtractorRegistry ¶
func NewContentExtractorRegistry() *ContentExtractorRegistry
NewContentExtractorRegistry creates a new registry. SEM@b4a403da2147ccb51a674e10d71891d4fccfe06a: build an empty content extractor registry (pure)
func (*ContentExtractorRegistry) FindExtractor ¶
func (r *ContentExtractorRegistry) FindExtractor(contentType string) (ContentExtractor, bool)
FindExtractor returns the first extractor that can handle the given content type. SEM@b4a403da2147ccb51a674e10d71891d4fccfe06a: return the first registered extractor that can handle the given content type (pure)
func (*ContentExtractorRegistry) Register ¶
func (r *ContentExtractorRegistry) Register(extractor ContentExtractor)
Register adds an extractor to the registry. SEM@b4a403da2147ccb51a674e10d71891d4fccfe06a: register a content extractor at the end of the priority list (mutates shared state)
type ContextAwareExtractor ¶
type ContextAwareExtractor interface {
ExtractCtx(ctx context.Context, data []byte, contentType string) (ExtractedContent, error)
}
ContextAwareExtractor is implemented by extractors that can receive a deadline-bearing context for cooperative cancellation. When an extractor implements both BoundedExtractor and ContextAwareExtractor, the pipeline's ExtractWithDeadline wrapper calls ExtractCtx with the timeout-bounded context so any wall-clock cancellation aborts in-flight reads through the archive's boundedReader (which checks ctx.Err() per Read call).
Extractors that only implement BoundedExtractor (without ContextAwareExtractor) still get a wall-clock deadline at the goroutine boundary, but in-flight I/O continues until it finishes naturally — the pipeline returns DeadlineExceeded promptly while the extractor goroutine drains in the background.
Extract should remain implemented as the legacy entry point and typically delegates to ExtractCtx with a context.Background(). SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: interface for extractors that accept a context for cooperative cancellation (pure)
type DOCXExtractor ¶
type DOCXExtractor struct {
// contains filtered or unexported fields
}
DOCXExtractor extracts Markdown-flavored text from a DOCX (OOXML) archive. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extractor that converts DOCX archives to Markdown-flavored text (pure)
func NewDOCXExtractor ¶
func NewDOCXExtractor(limits Limits) *DOCXExtractor
NewDOCXExtractor returns an extractor configured with the given limits. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: build a DOCXExtractor configured with the given extraction limits (pure)
func (*DOCXExtractor) Bounded ¶
func (e *DOCXExtractor) Bounded() bool
Bounded marks DOCXExtractor as needing a wall-clock deadline. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: signal that this extractor requires a wall-clock deadline context (pure)
func (*DOCXExtractor) CanHandle ¶
func (e *DOCXExtractor) CanHandle(contentType string) bool
CanHandle returns true iff contentType is the DOCX OOXML MIME type. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: validate that the content type matches the DOCX OOXML MIME type (pure)
func (*DOCXExtractor) Extract ¶
func (e *DOCXExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
Extract parses a DOCX archive and produces Markdown-flavored text. This is the legacy entry point that delegates to ExtractCtx with a background context (no cooperative cancellation).
On non-nil error, the returned ExtractedContent is zero and must be discarded. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: parse a DOCX archive and return Markdown text using a background context
func (*DOCXExtractor) ExtractCtx ¶
func (e *DOCXExtractor) ExtractCtx(ctx context.Context, data []byte, contentType string) (ExtractedContent, error)
ExtractCtx is the context-aware extraction entry point used by the pipeline's ExtractWithDeadline wrapper. The supplied ctx is wired into the OOXML archive so that all member-level boundedReaders abort their reads on cancellation (wall-clock deadline or parent cancel).
On non-nil error, the returned ExtractedContent is zero and must be discarded. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: parse a DOCX archive with context cancellation and return Markdown text and title
func (*DOCXExtractor) Name ¶
func (e *DOCXExtractor) Name() string
Name returns the extractor name as registered with the registry. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: return the registered extractor name for DOCX files (pure)
type EntityReference ¶
type EntityReference struct {
EntityType string // "asset", "threat", "document", "note", "diagram", "repository"
EntityID string // UUID of the source entity
URI string // External URL (empty for DB-resident content)
Name string // Display name for progress reporting
}
EntityReference identifies a source entity for content extraction. For DB-resident content (notes, assets), URI is empty and the provider reads directly from the database using EntityType + EntityID. For external content (documents with URLs), URI is the fetch target. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: identifies a source entity for content extraction by type, ID, and optional URI (pure)
type ExtractedContent ¶
type ExtractedContent struct {
Text string // Extracted plain text
Title string // Document title if available
ContentType string // Original content type (e.g., "application/pdf")
Metadata map[string]string // Provider-specific metadata
}
ExtractedContent holds the text extracted from a source entity. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: holds plain text and metadata produced by a content extractor (pure)
func ExtractWithDeadline ¶
func ExtractWithDeadline(ctx context.Context, budget time.Duration, fn func(context.Context) (ExtractedContent, error)) (ExtractedContent, error)
ExtractWithDeadline runs an extraction function under a wall-clock budget, returning early if the budget elapses. It is the entry point the extractor worker uses to bound CPU/memory-heavy extractors on adversarial input. On timeout it returns context.DeadlineExceeded; on parent cancellation it returns ctx.Err(). The wrapped fn receives the deadline-bearing context so cooperative cancellation is possible. SEM@4359a42e5ac4f24a1d76d8c8c8455c6cc91541c5: run an extractor under a wall-clock budget, cancelling on timeout or parent context
type HTMLExtractor ¶
type HTMLExtractor struct{}
HTMLExtractor extracts visible text from HTML content, stripping script and style elements. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extracts visible text from HTML content, excluding script and style elements (pure)
func NewHTMLExtractor ¶
func NewHTMLExtractor() *HTMLExtractor
NewHTMLExtractor creates a new HTMLExtractor. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: build a new HTMLExtractor (pure)
func (*HTMLExtractor) CanHandle ¶
func (e *HTMLExtractor) CanHandle(contentType string) bool
CanHandle returns true for text/html content types. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: report whether the content type is text/html (pure)
func (*HTMLExtractor) Extract ¶
func (e *HTMLExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
Extract strips HTML tags and returns the visible text. Script and style element content is excluded. SEM@f69d82c5864c65f768181d82416962e3bbd63667: parse HTML bytes and return visible text as extracted content (pure)
func (*HTMLExtractor) Name ¶
func (e *HTMLExtractor) Name() string
Name returns the extractor name. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: return the extractor's identifying name (pure)
type Limits ¶
type Limits struct {
CompressedSizeBytes int64
DecompressedSizeBytes int64
PartSizeBytes int64
MarkdownSizeBytes int64
MaxXMLElementDepth int
MaxCompressionRatio int64
PPTXSlides int
XLSXCells int
// WallClockBudget is the per-extraction deadline (0 disables).
WallClockBudget time.Duration
}
Limits is the set of extraction caps the OOXML opener, the XML decoder, and the wall-clock budget enforce. Relocated and exported from the package-private ooxmlLimits. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: extraction size and depth caps applied to OOXML, XML decoding, and wall-clock budget (pure)
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits returns the design-spec default values. SEM@f7dfe970572e2574027691de97c695d5ae39d5b7: return design-spec default extraction limits (pure)
type PDFExtractor ¶
type PDFExtractor struct{}
PDFExtractor extracts plain text from PDF binary content. Because the PDF library requires a seekable reader, the bytes are written to a temporary file which is removed after extraction. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extractor that converts PDF binary content to plain text via a temporary file (pure)
func NewPDFExtractor ¶
func NewPDFExtractor() *PDFExtractor
NewPDFExtractor creates a new PDFExtractor. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: build a PDFExtractor instance (pure)
func (*PDFExtractor) CanHandle ¶
func (e *PDFExtractor) CanHandle(contentType string) bool
CanHandle returns true for application/pdf content types. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: validate that a content type is application/pdf (pure)
func (*PDFExtractor) Extract ¶
func (e *PDFExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
Extract writes the PDF bytes to a temp file and extracts plain text page by page. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: convert PDF bytes to plain text via a temporary file, returning extracted content
func (*PDFExtractor) Name ¶
func (e *PDFExtractor) Name() string
Name returns the extractor name. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: return the canonical name of the PDF extractor (pure)
type PPTXExtractor ¶
type PPTXExtractor struct {
// contains filtered or unexported fields
}
PPTXExtractor extracts Markdown-flavored text from a PPTX (OOXML) archive. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extractor for PPTX files that converts slides to Markdown text within configured limits (pure)
func NewPPTXExtractor ¶
func NewPPTXExtractor(limits Limits) *PPTXExtractor
NewPPTXExtractor returns an extractor configured with the given limits. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: build a PPTXExtractor configured with the given resource limits (pure)
func (*PPTXExtractor) Bounded ¶
func (e *PPTXExtractor) Bounded() bool
Bounded marks PPTXExtractor as needing a wall-clock deadline. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: report that this extractor requires a wall-clock deadline (pure)
func (*PPTXExtractor) CanHandle ¶
func (e *PPTXExtractor) CanHandle(contentType string) bool
CanHandle returns true iff contentType is the PPTX OOXML MIME type. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: report whether the content type is the PPTX OOXML MIME type (pure)
func (*PPTXExtractor) Extract ¶
func (e *PPTXExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
Extract parses a PPTX archive and produces Markdown-flavored text. This is the legacy entry point that delegates to ExtractCtx with a background context (no cooperative cancellation).
On non-nil error, the returned ExtractedContent is zero and must be discarded. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: parse a PPTX archive and return Markdown text using a background context (pure)
func (*PPTXExtractor) ExtractCtx ¶
func (e *PPTXExtractor) ExtractCtx(ctx context.Context, data []byte, contentType string) (ExtractedContent, error)
ExtractCtx is the context-aware extraction entry point. Slides appear in document order under "## Slide N: <title>" headings; hidden slides are skipped but still consume slide numbers. Speaker notes (when present) follow each slide as a "### Notes" subsection. The supplied ctx is wired into the archive so all member-level reads abort on cancellation.
On non-nil error, the returned ExtractedContent is zero and must be discarded. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: parse a PPTX archive into Markdown with slide headings, speaker notes, and cancellation support (pure)
func (*PPTXExtractor) Name ¶
func (e *PPTXExtractor) Name() string
Name returns the extractor name as registered with the registry. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: return the extractor's registry name "pptx" (pure)
type PlainTextExtractor ¶
type PlainTextExtractor struct{}
PlainTextExtractor extracts content from plain text and CSV content types. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extractor for plain text and CSV content types (pure)
func NewPlainTextExtractor ¶
func NewPlainTextExtractor() *PlainTextExtractor
NewPlainTextExtractor creates a new PlainTextExtractor. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: build a PlainTextExtractor (pure)
func (*PlainTextExtractor) CanHandle ¶
func (e *PlainTextExtractor) CanHandle(contentType string) bool
CanHandle returns true for text/plain and text/csv content types. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: report whether the extractor handles text/plain or text/csv content types (pure)
func (*PlainTextExtractor) Extract ¶
func (e *PlainTextExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
Extract returns the raw bytes as a string with no transformation. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: convert raw bytes to extracted content with no transformation (pure)
func (*PlainTextExtractor) Name ¶
func (e *PlainTextExtractor) Name() string
Name returns the extractor name. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: return the extractor's canonical name (pure)
type TextChunker ¶
type TextChunker struct {
// contains filtered or unexported fields
}
TextChunker splits text into chunks suitable for embedding SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: splits text into overlapping chunks sized for embedding (pure)
func NewTextChunker ¶
func NewTextChunker(maxChunkSize, overlap int) *TextChunker
NewTextChunker creates a chunker with the given size and overlap (in characters) SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: build a TextChunker with a given max chunk size and overlap in characters (pure)
func (*TextChunker) Chunk ¶
func (tc *TextChunker) Chunk(text string) []string
Chunk splits text into chunks at sentence boundaries SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: split text into sentence-boundary-aligned chunks with optional overlap (pure)
type XLSXExtractor ¶
type XLSXExtractor struct {
// contains filtered or unexported fields
}
XLSXExtractor extracts Markdown-flavored text from an XLSX (OOXML) workbook. Uses github.com/xuri/excelize/v2 for archive parsing, shared-strings handling, and number-format rendering. Limit enforcement (cell count, markdown cap) is applied during the streaming render.
Header detection follows the design spec: a per-row style fingerprint (dominant bgColor, fontSize, fontWeight, fontItalic) is computed across the first ≤5 non-empty rows, with a content-heuristic fallback when style fingerprints are uniform across the inspected rows. See xlsxDetectHeader. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extractor that converts XLSX workbook sheets to Markdown pipe tables within configured limits
func NewXLSXExtractor ¶
func NewXLSXExtractor(limits Limits) *XLSXExtractor
NewXLSXExtractor returns an extractor configured with the given limits. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: build an XLSXExtractor configured with the given extraction limits (pure)
func (*XLSXExtractor) Bounded ¶
func (e *XLSXExtractor) Bounded() bool
Bounded marks XLSXExtractor as needing a wall-clock deadline. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: report that this extractor requires a wall-clock deadline (pure)
func (*XLSXExtractor) CanHandle ¶
func (e *XLSXExtractor) CanHandle(contentType string) bool
CanHandle returns true iff contentType is the XLSX OOXML MIME type. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: report whether the content type matches the XLSX OOXML MIME type (pure)
func (*XLSXExtractor) Extract ¶
func (e *XLSXExtractor) Extract(data []byte, contentType string) (ExtractedContent, error)
Extract opens the workbook, walks visible sheets in tab order, and writes Markdown-flavored text into a bounded markdown builder. This is the legacy entry point that delegates to ExtractCtx with a background context (no cooperative cancellation).
On non-nil error, the returned ExtractedContent is zero and must be discarded. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extract Markdown text from XLSX bytes without cooperative cancellation
func (*XLSXExtractor) ExtractCtx ¶
func (e *XLSXExtractor) ExtractCtx(ctx context.Context, data []byte, contentType string) (ExtractedContent, error)
ExtractCtx is the context-aware extraction entry point. Each visible sheet is rendered as `## Sheet: <name>` followed by a pipe table of trimmed cells. The supplied ctx is checked between sheets and inside the row loop so wall-clock cancellation aborts long workbooks promptly.
On non-nil error, the returned ExtractedContent is zero and must be discarded. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: extract Markdown pipe tables from all visible XLSX sheets with context cancellation and limit enforcement
func (*XLSXExtractor) Name ¶
func (e *XLSXExtractor) Name() string
Name returns the extractor name as registered with the registry. SEM@d1c9c93fe4dd63680a390679e8df436b39c27a8b: return the registered extractor name for XLSX files (pure)