package shared import ( "fmt" "strings" "gitea.maximumdirect.net/eric/notarius/internal/core/source" ) // CitationResolver resolves cited ranges against one source document. type CitationResolver struct { doc *source.SourceDocument index source.DocumentIndex } // NewCitationResolver prepares citation resolution for doc. func NewCitationResolver(doc *source.SourceDocument) (*CitationResolver, error) { if doc == nil { return nil, fmt.Errorf("source document must not be nil") } return &CitationResolver{doc: doc, index: source.NewDocumentIndex(doc)}, nil } // CitedText resolves cited source ranges in document order, including each // source unit once, and joins the resulting text with newlines. func (r *CitationResolver) CitedText(refs []source.SourceRef) (string, error) { included := make([]bool, len(r.doc.Units)) for _, ref := range refs { if err := r.index.ValidateRef(ref); err != nil { return "", fmt.Errorf("resolve cited source range: %w", err) } start, _ := r.index.Position(ref.StartUnitID) end, _ := r.index.Position(ref.EndUnitID) for index := start; index <= end; index++ { included[index] = true } } parts := make([]string, 0, len(r.doc.Units)) for index, unit := range r.doc.Units { if included[index] { parts = append(parts, unit.Text) } } return strings.Join(parts, "\n"), nil }