From d566466308faf7f5d017edd6118bafd5f35bc56a Mon Sep 17 00:00:00 2001 From: Ian Davis <18375+iand@users.noreply.github.com> Date: Fri, 23 Jan 2026 12:52:10 +0000 Subject: [PATCH 1/2] Add documentation for exported functions --- decoder.go | 4 +- doc.go | 115 +++++++++++++++++ encoder.go | 9 +- helpers.go | 29 ++++- scanner.go | 36 ++++-- types.go | 364 ++++++++++++++++++++++++++++++----------------------- 6 files changed, 380 insertions(+), 177 deletions(-) create mode 100644 doc.go diff --git a/decoder.go b/decoder.go index 317bb68..08b5613 100644 --- a/decoder.go +++ b/decoder.go @@ -3,7 +3,6 @@ This is free and unencumbered software released into the public domain. For more information, see or the accompanying UNLICENSE file. */ -// Package gedcom provides a functions to parse GEDCOM files. package gedcom import ( @@ -31,6 +30,9 @@ func NewDecoder(r io.Reader) *Decoder { } } +// LogUnhandledTags configures the decoder to log any unrecognized GEDCOM tags +// to the provided writer. This is useful for debugging GEDCOM files that +// contain non-standard or vendor-specific tags. func (d *Decoder) LogUnhandledTags(w io.Writer) { d.tagLogger = log.New(w, "", log.Lshortfile) } diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..dc6454a --- /dev/null +++ b/doc.go @@ -0,0 +1,115 @@ +/* +This is free and unencumbered software released into the public domain. For more +information, see or the accompanying UNLICENSE file. +*/ + +/* +Package gedcom provides functions to parse and produce GEDCOM files. + +GEDCOM (Genealogical Data Communication) is a standard format used for +exchanging genealogical data between software applications. This package +includes functionality for both parsing existing GEDCOM files and generating +new ones. + +# Decoding GEDCOM Files + +The package provides a streaming [Decoder] for reading GEDCOM files. Use +[NewDecoder] to create a decoder that reads from an [io.Reader]: + + data, err := os.ReadFile("family.ged") + if err != nil { + log.Fatal(err) + } + + d := gedcom.NewDecoder(bytes.NewReader(data)) + g, err := d.Decode() + if err != nil { + log.Fatal(err) + } + + for _, ind := range g.Individual { + if len(ind.Name) > 0 { + fmt.Println(ind.Name[0].Name) + } + } + +The decoder is streaming and can handle large files without loading the entire +contents into memory. + +# Encoding GEDCOM Files + +The package also provides an [Encoder] for generating GEDCOM files. Use +[NewEncoder] to create an encoder that writes to an [io.Writer]: + + g := &gedcom.Gedcom{ + Header: &gedcom.Header{ + SourceSystem: gedcom.SystemRecord{ + Xref: "MyApp", + ProductName: "My Application", + }, + CharacterSet: "UTF-8", + }, + Individual: []*gedcom.IndividualRecord{ + { + Xref: "I1", + Name: []*gedcom.NameRecord{ + {Name: "John /Doe/"}, + }, + Sex: "M", + }, + }, + Trailer: &gedcom.Trailer{}, + } + + f, err := os.Create("output.ged") + if err != nil { + log.Fatal(err) + } + defer f.Close() + + enc := gedcom.NewEncoder(f) + if err := enc.Encode(g); err != nil { + log.Fatal(err) + } + +# Data Model + +The [Gedcom] struct is the top-level container returned by the decoder and +accepted by the encoder. It contains slices of records for individuals, +families, sources, and other GEDCOM record types. + +[IndividualRecord] represents a person and contains their names, sex, life +events (birth, death, etc.), family links, and citations. + +[FamilyRecord] represents a family unit and links to husband, wife, and +children as [IndividualRecord] pointers. + +[EventRecord] is a flexible type used for both events (birth, death, marriage) +and attributes (occupation, residence). The Tag field indicates the event type. + +[SourceRecord] and [CitationRecord] handle source citations for genealogical +claims. + +# Name Parsing + +The [SplitPersonalName] helper function parses GEDCOM-formatted names: + + parsed := gedcom.SplitPersonalName("John \"Jack\" /Smith/ Jr.") + // parsed.Given = "John" + // parsed.Nickname = "Jack" + // parsed.Surname = "Smith" + // parsed.Suffix = "Jr." + +# User-Defined Tags + +GEDCOM allows custom tags prefixed with an underscore. These are captured in +[UserDefinedTag] slices on most record types, preserving vendor-specific +extensions. + +# Specification Coverage + +This package implements approximately 80% of the GEDCOM 5.5 specification, +which is sufficient for parsing about 99% of real-world GEDCOM files. It has +not been extensively tested with non-ASCII character sets. +*/ +package gedcom diff --git a/encoder.go b/encoder.go index c902019..159b879 100644 --- a/encoder.go +++ b/encoder.go @@ -12,7 +12,12 @@ import ( "strings" ) -// An Encoder encodes and writes GEDCOM objects to an input stream. +// Encoder writes GEDCOM-encoded data to an output stream. +// Use [NewEncoder] to create an Encoder and [Encoder.Encode] to write +// a [Gedcom] structure. +// +// The encoder handles GEDCOM line length limits automatically, using +// CONT (continuation) and CONC (concatenation) tags to split long text. type Encoder struct { w *bufio.Writer err error @@ -26,6 +31,8 @@ func NewEncoder(w io.Writer) *Encoder { } } +// Encode writes the GEDCOM-encoded representation of g to the encoder's output stream. +// It writes the header, all records (individuals, families, sources, etc.), and trailer. func (e *Encoder) Encode(g *Gedcom) error { e.header(g.Header) diff --git a/helpers.go b/helpers.go index 53282a6..c3723e8 100644 --- a/helpers.go +++ b/helpers.go @@ -4,15 +4,32 @@ import ( "strings" ) +// ParsedName contains the components of a personal name after parsing +// with [SplitPersonalName]. type ParsedName struct { - Full string - Given string - Surname string - Suffix string - Nickname string + Full string // Reconstructed full name without GEDCOM delimiters + Given string // Given name(s) / first name(s) + Surname string // Surname / family name / last name + Suffix string // Name suffix (e.g., "Jr.", "III", "PhD") + Nickname string // Nickname, if present in quotes } -// SplitPersonalName parses a name in the format "First Name /Surname/ suffix" into its components. +// SplitPersonalName parses a GEDCOM-formatted personal name into its components. +// GEDCOM names use slashes to delimit the surname: "Given Names /Surname/ Suffix". +// +// Examples: +// +// SplitPersonalName("John /Smith/") +// // Returns: Given="John", Surname="Smith" +// +// SplitPersonalName("John \"Jack\" /Smith/ Jr.") +// // Returns: Given="John", Nickname="Jack", Surname="Smith", Suffix="Jr." +// +// SplitPersonalName("Mary Jane /van der Berg/") +// // Returns: Given="Mary Jane", Surname="van der Berg" +// +// The function also handles alternative surnames separated by slashes within +// the surname delimiters (e.g., "/Smith/Smyth/" becomes Surname="Smith/Smyth"). func SplitPersonalName(name string) ParsedName { name = strings.TrimSpace(name) diff --git a/scanner.go b/scanner.go index 7fb883c..bcfb9bf 100644 --- a/scanner.go +++ b/scanner.go @@ -11,15 +11,19 @@ import ( "strconv" ) +// Line represents a single line from a GEDCOM file after tokenization. +// A GEDCOM line has the format: "level [xref] tag [value]" +// For example: "0 @I1@ INDI" or "1 NAME John /Smith/" type Line struct { - Level int - Tag string - Value string - Xref string - LineNumber int // the line number of the input file - Offset int // the character offset in the input file + Level int // Hierarchy level (0 for top-level records) + Tag string // GEDCOM tag (e.g., "INDI", "NAME", "BIRT") + Value string // Optional value following the tag + Xref string // Optional cross-reference identifier (e.g., "I1" from "@I1@") + LineNumber int // Line number in the input file (1-indexed) + Offset int // Character offset in the input file } +// String returns the line in GEDCOM format. func (l *Line) String() string { if l.Xref != "" { return fmt.Sprintf("%d @%s@ %s %s", l.Level, l.Xref, l.Tag, l.Value) @@ -27,7 +31,12 @@ func (l *Line) String() string { return fmt.Sprintf("%d %s %s", l.Level, l.Tag, l.Value) } -// A Scanner is a GEDCOM scanning state machine. +// Scanner tokenizes GEDCOM input line by line. It is a low-level component +// used by [Decoder]. Most users should use [Decoder] directly instead. +// +// A Scanner reads from an [io.RuneScanner] and breaks the input into +// GEDCOM lines, parsing the level, optional cross-reference, tag, and +// optional value from each line. type Scanner struct { r io.RuneScanner err error @@ -41,7 +50,9 @@ type Scanner struct { xref string } -// NewScanner creates a new Scanner ready for use. +// NewScanner creates a new Scanner that reads from r. +// Use [Scanner.Next] to advance through the input and [Scanner.Line] +// to retrieve the current line after each successful call to Next. func NewScanner(r io.RuneScanner) *Scanner { return &Scanner{ r: r, @@ -307,10 +318,13 @@ func (s *Scanner) Err() error { return s.err } +// ScanErr represents a scanning error with location information. +// It wraps the underlying error and includes the line number and +// character offset where the error occurred. type ScanErr struct { - Err error - LineNumber int - Offset int + Err error // The underlying error + LineNumber int // Line number where the error occurred (1-indexed) + Offset int // Character offset within the line } func (e *ScanErr) Error() string { diff --git a/types.go b/types.go index cadd09e..dd9b07c 100644 --- a/types.go +++ b/types.go @@ -5,6 +5,8 @@ information, see or the accompanying UNLICENSE file. package gedcom +// Gedcom represents a complete GEDCOM file. It is the top-level container +// returned by [Decoder.Decode] and accepted by [Encoder.Encode]. type Gedcom struct { Header *Header Family []*FamilyRecord @@ -50,230 +52,274 @@ type SystemRecord struct { UserDefined []UserDefinedTag } +// SubmissionRecord contains information about a batch submission of genealogical data. type SubmissionRecord struct { Xref string } +// Trailer marks the end of a GEDCOM file. It contains no data. type Trailer struct{} +// FamilyRecord represents a family unit in GEDCOM. It links individuals +// together as husband, wife, and children, and contains family events +// such as marriage, divorce, and census records. type FamilyRecord struct { - Xref string - Husband *IndividualRecord - Wife *IndividualRecord - Child []*IndividualRecord - Event []*EventRecord - NumberOfChildren string - UserReference []*UserReferenceRecord - AutomatedRecordId string - Change ChangeRecord - Note []*NoteRecord - Citation []*CitationRecord - Media []*MediaRecord - UserDefined []UserDefinedTag + Xref string // Unique cross-reference identifier for this family (e.g., "@F1@") + Husband *IndividualRecord // Pointer to the husband/father individual + Wife *IndividualRecord // Pointer to the wife/mother individual + Child []*IndividualRecord // Pointers to child individuals + Event []*EventRecord // Family events (marriage, divorce, census, etc.) + NumberOfChildren string // Total number of children, may differ from len(Child) + UserReference []*UserReferenceRecord // User-provided reference numbers + AutomatedRecordId string // Unique record ID assigned by the source system + Change ChangeRecord // Record of when this record was last modified + Note []*NoteRecord // Notes attached to this family + Citation []*CitationRecord // Source citations for this family + Media []*MediaRecord // Media objects (photos, documents) for this family + UserDefined []UserDefinedTag // User-defined tags (prefixed with underscore) } +// IndividualRecord represents a person in GEDCOM. It contains the person's +// names, sex, life events, attributes, and links to their families. type IndividualRecord struct { - Xref string - Name []*NameRecord - Sex string - Event []*EventRecord - Attribute []*EventRecord - Parents []*FamilyLinkRecord - Family []*FamilyLinkRecord - Submitter []*SubmitterRecord - Association []*AssociationRecord - PermanentRecordFileNumber string - AncestralFileNumber string - UserReference []*UserReferenceRecord - AutomatedRecordId string - Change ChangeRecord - Note []*NoteRecord - Citation []*CitationRecord - Media []*MediaRecord - UserDefined []UserDefinedTag + Xref string // Unique cross-reference identifier (e.g., "@I1@") + Name []*NameRecord // Names (may have multiple for maiden names, aliases) + Sex string // Sex: "M" for male, "F" for female, "U" for unknown + Event []*EventRecord // Life events (birth, death, burial, etc.) + Attribute []*EventRecord // Attributes (occupation, residence, education, etc.) + Parents []*FamilyLinkRecord // Links to families where this person is a child + Family []*FamilyLinkRecord // Links to families where this person is a spouse + Submitter []*SubmitterRecord // Submitters of this record + Association []*AssociationRecord // Associations with other individuals + PermanentRecordFileNumber string // Permanent record file number + AncestralFileNumber string // Ancestral file number + UserReference []*UserReferenceRecord // User-provided reference numbers + AutomatedRecordId string // Unique record ID assigned by the source system + Change ChangeRecord // Record of when this record was last modified + Note []*NoteRecord // Notes attached to this individual + Citation []*CitationRecord // Source citations for this individual + Media []*MediaRecord // Media objects (photos, documents) + UserDefined []UserDefinedTag // User-defined tags (prefixed with underscore) } +// MediaRecord represents a multimedia object such as a photo, document, +// or audio/video recording. It can be referenced by individuals, families, +// events, and sources. type MediaRecord struct { - Xref string - File []*FileRecord - Title string - UserReference []*UserReferenceRecord - AutomatedRecordId string - Change ChangeRecord - Note []*NoteRecord - Citation []*CitationRecord - UserDefined []UserDefinedTag + Xref string // Unique cross-reference identifier (e.g., "@M1@") + File []*FileRecord // File references for this media object + Title string // Title or description of the media + UserReference []*UserReferenceRecord // User-provided reference numbers + AutomatedRecordId string // Unique record ID assigned by the source system + Change ChangeRecord // Record of when this record was last modified + Note []*NoteRecord // Notes attached to this media + Citation []*CitationRecord // Source citations + UserDefined []UserDefinedTag // User-defined tags } +// FileRecord contains information about a multimedia file. type FileRecord struct { - Name string - Format string - FormatType string - Title string - UserDefined []UserDefinedTag + Name string // File path or URL + Format string // File format (e.g., "jpeg", "gif", "pdf") + FormatType string // Media type (e.g., "photo", "document") + Title string // Title or caption for this file + UserDefined []UserDefinedTag // User-defined tags } +// UserReferenceRecord contains a user-defined reference number for a record. type UserReferenceRecord struct { - Number string - Type string + Number string // The reference number + Type string // The type of reference } +// ChangeRecord indicates when a record was last modified. type ChangeRecord struct { - Date string - Time string - Note []*NoteRecord + Date string // Date of the change in GEDCOM date format + Time string // Time of the change + Note []*NoteRecord // Notes about the change } +// RepositoryRecord represents a repository where source documents are held, +// such as a library, archive, or private collection. type RepositoryRecord struct { - Xref string - Name string - Address AddressRecord - Note []*NoteRecord - UserReference []*UserReferenceRecord - AutomatedRecordId string - Change ChangeRecord - UserDefined []UserDefinedTag + Xref string // Unique cross-reference identifier (e.g., "@R1@") + Name string // Name of the repository + Address AddressRecord // Address of the repository + Note []*NoteRecord // Notes about the repository + UserReference []*UserReferenceRecord // User-provided reference numbers + AutomatedRecordId string // Unique record ID assigned by the source system + Change ChangeRecord // Record of when this record was last modified + UserDefined []UserDefinedTag // User-defined tags } +// SourceRecord represents a source of genealogical information, such as +// a book, document, website, or oral interview. type SourceRecord struct { - Xref string - Title string - Data *SourceDataRecord - Originator string - FiledBy string - PublicationFacts string - Text string - Repository *SourceRepositoryRecord - UserReference []*UserReferenceRecord - AutomatedRecordId string - Change ChangeRecord - Note []*NoteRecord - Media []*MediaRecord - UserDefined []UserDefinedTag + Xref string // Unique cross-reference identifier (e.g., "@S1@") + Title string // Title of the source + Data *SourceDataRecord // Data recorded from the source + Originator string // Author or creator of the source + FiledBy string // Person who filed the source + PublicationFacts string // Publication information + Text string // Verbatim text from the source + Repository *SourceRepositoryRecord // Repository where the source is held + UserReference []*UserReferenceRecord // User-provided reference numbers + AutomatedRecordId string // Unique record ID assigned by the source system + Change ChangeRecord // Record of when this record was last modified + Note []*NoteRecord // Notes about the source + Media []*MediaRecord // Media objects (photos of documents, etc.) + UserDefined []UserDefinedTag // User-defined tags } +// SourceDataRecord contains data recorded from a source. type SourceDataRecord struct { - Event []*SourceEventRecord + Event []*SourceEventRecord // Events covered by the source } +// SourceEventRecord describes an event type covered by a source. type SourceEventRecord struct { - Kind string - Date string - Place string + Kind string // Type of event (e.g., "BIRT", "MARR", "DEAT") + Date string // Date range covered by the source + Place string // Place jurisdiction covered by the source } +// SourceRepositoryRecord links a source to its repository. type SourceRepositoryRecord struct { - Repository *RepositoryRecord - Note []*NoteRecord - CallNumber []*SourceCallNumberRecord + Repository *RepositoryRecord // The repository holding the source + Note []*NoteRecord // Notes about the source at this repository + CallNumber []*SourceCallNumberRecord // Call numbers for locating the source } +// SourceCallNumberRecord contains a call number for a source in a repository. type SourceCallNumberRecord struct { - CallNumber string - MediaType string + CallNumber string // The call number or shelf location + MediaType string // Type of media (e.g., "book", "microfilm") } +// CitationRecord represents a citation to a source for a specific claim. +// It links to a [SourceRecord] and provides details about where in the +// source the information was found. type CitationRecord struct { - Source *SourceRecord - Page string - Data DataRecord - Quay string - Media []*MediaRecord - Note []*NoteRecord - UserDefined []UserDefinedTag + Source *SourceRecord // The source being cited + Page string // Page number or location within the source + Data DataRecord // Data extracted from the source + Quay string // Quality assessment (0-3, with 3 being direct evidence) + Media []*MediaRecord // Media objects (e.g., photo of the source page) + Note []*NoteRecord // Notes about this citation + UserDefined []UserDefinedTag // User-defined tags } +// SubmitterRecord contains information about the person or organization +// that submitted the genealogical data. type SubmitterRecord struct { - Xref string - Name string - Address *AddressRecord - Media []*MediaRecord - Language []string - SubmitterRecordFileID string - AutomatedRecordId string - Note []*NoteRecord - Change *ChangeRecord + Xref string // Unique cross-reference identifier (e.g., "@SUBM1@") + Name string // Name of the submitter + Address *AddressRecord // Address of the submitter + Media []*MediaRecord // Media objects (e.g., photo of submitter) + Language []string // Languages used by the submitter + SubmitterRecordFileID string // Submitter record file identifier + AutomatedRecordId string // Unique record ID assigned by the source system + Note []*NoteRecord // Notes from the submitter + Change *ChangeRecord // Record of when this record was last modified } +// NameRecord represents a name for an individual. An individual may have +// multiple names (e.g., maiden name, married name, aliases). +// The Name field contains the full name in GEDCOM format: "Given Name /Surname/ Suffix". +// Use [SplitPersonalName] to parse the Name field into components. type NameRecord struct { - Name string - Type string - NamePiecePrefix string - NamePieceGiven string - NamePieceNick string - NamePieceSurnamePrefix string - NamePieceSurname string - NamePieceSuffix string - Phonetic []*VariantNameRecord - Romanized []*VariantNameRecord - Citation []*CitationRecord - Note []*NoteRecord - UserDefined []UserDefinedTag + Name string // Full name in GEDCOM format (e.g., "John /Smith/ Jr.") + Type string // Name type (e.g., "birth", "married", "aka") + NamePiecePrefix string // Name prefix (e.g., "Dr.", "Rev.") + NamePieceGiven string // Given name(s) + NamePieceNick string // Nickname + NamePieceSurnamePrefix string // Surname prefix (e.g., "van", "de") + NamePieceSurname string // Surname + NamePieceSuffix string // Name suffix (e.g., "Jr.", "III") + Phonetic []*VariantNameRecord // Phonetic variants of the name + Romanized []*VariantNameRecord // Romanized variants of the name + Citation []*CitationRecord // Source citations for this name + Note []*NoteRecord // Notes about this name + UserDefined []UserDefinedTag // User-defined tags } +// VariantNameRecord represents a phonetic or romanized variant of a name. type VariantNameRecord struct { - Name string - Type string - NamePiecePrefix string - NamePieceGiven string - NamePieceNick string - NamePieceSurnamePrefix string - NamePieceSurname string - NamePieceSuffix string - Citation []*CitationRecord - Note []*NoteRecord + Name string // Full variant name + Type string // Variant type (e.g., "kana", "hangul" for phonetic) + NamePiecePrefix string // Name prefix + NamePieceGiven string // Given name(s) + NamePieceNick string // Nickname + NamePieceSurnamePrefix string // Surname prefix + NamePieceSurname string // Surname + NamePieceSuffix string // Name suffix + Citation []*CitationRecord // Source citations + Note []*NoteRecord // Notes } +// DataRecord contains data extracted from a source citation. type DataRecord struct { - Date string - Text []string - UserDefined []UserDefinedTag + Date string // Date the data was recorded + Text []string // Verbatim text from the source + UserDefined []UserDefinedTag // User-defined tags } +// EventRecord represents an event or attribute in a person's or family's life. +// Common event tags include BIRT (birth), DEAT (death), MARR (marriage), +// BURI (burial), CHR (christening), DIV (divorce). +// Common attribute tags include OCCU (occupation), RESI (residence), +// EDUC (education), RELI (religion). type EventRecord struct { - Tag string - Value string - Type string - Date string - Place PlaceRecord - Address AddressRecord - Age string - ResponsibleAgency string - ReligiousAffiliation string - Cause string - RestrictionNotice string // 5.5.1 - ChildInFamily *FamilyRecord // link to parent family for birth events - AdoptedByParent string // for adoption event, one of HUSB,WIFE,BOTH - Citation []*CitationRecord - Media []*MediaRecord - Note []*NoteRecord - UserDefined []UserDefinedTag + Tag string // Event type tag (e.g., "BIRT", "DEAT", "MARR") + Value string // Event value, often "Y" to indicate event occurred + Type string // Detailed event type for generic EVEN tags + Date string // Date in GEDCOM date format + Place PlaceRecord // Location where the event occurred + Address AddressRecord // Address associated with the event + Age string // Age of the individual at the time of the event + ResponsibleAgency string // Agency responsible for the record + ReligiousAffiliation string // Religious affiliation associated with event + Cause string // Cause (e.g., cause of death) + RestrictionNotice string // Privacy restriction (GEDCOM 5.5.1) + ChildInFamily *FamilyRecord // Link to parent family for birth events + AdoptedByParent string // For adoption: "HUSB", "WIFE", or "BOTH" + Citation []*CitationRecord // Source citations for this event + Media []*MediaRecord // Media objects (e.g., photos, certificates) + Note []*NoteRecord // Notes about this event + UserDefined []UserDefinedTag // User-defined tags } +// NoteRecord contains a note or comment attached to a record. type NoteRecord struct { - Note string - Citation []*CitationRecord + Note string // The note text + Citation []*CitationRecord // Source citations for the note } +// PlaceRecord represents a geographic location. The Name field typically +// contains a comma-separated jurisdiction hierarchy (e.g., "City, County, State, Country"). type PlaceRecord struct { - Name string - Phonetic []*VariantPlaceNameRecord - Romanized []*VariantPlaceNameRecord - Latitude string - Longitude string - Citation []*CitationRecord - Note []*NoteRecord + Name string // Place name (jurisdiction hierarchy) + Phonetic []*VariantPlaceNameRecord // Phonetic variants of the place name + Romanized []*VariantPlaceNameRecord // Romanized variants of the place name + Latitude string // Latitude in GEDCOM format (e.g., "N50.9333") + Longitude string // Longitude in GEDCOM format (e.g., "W1.8") + Citation []*CitationRecord // Source citations + Note []*NoteRecord // Notes about the place } +// VariantPlaceNameRecord represents a phonetic or romanized variant of a place name. type VariantPlaceNameRecord struct { - Name string - Type string + Name string // The variant place name + Type string // Variant type (e.g., "kana", "hangul" for phonetic) } +// FamilyLinkRecord links an individual to a family. It is used both for +// linking children to their parents (via [IndividualRecord.Parents]) and +// for linking spouses to their families (via [IndividualRecord.Family]). type FamilyLinkRecord struct { - Family *FamilyRecord - Type string - Note []*NoteRecord + Family *FamilyRecord // Pointer to the linked family + Type string // Relationship type (e.g., "birth", "adopted", "foster") + Note []*NoteRecord // Notes about this family link } // See https://www.tamurajones.net/GEDCOMADDR.xhtml for very informative analysis of the ADDR structure @@ -306,9 +352,11 @@ type UserDefinedTag struct { UserDefined []UserDefinedTag } +// AssociationRecord links an individual to another person with a defined +// relationship, such as godparent, witness, or friend. type AssociationRecord struct { - Xref string - Relation string - Citation []*CitationRecord - Note []*NoteRecord + Xref string // Cross-reference to the associated individual + Relation string // Relationship type (e.g., "godparent", "witness") + Citation []*CitationRecord // Source citations + Note []*NoteRecord // Notes about this association } From 665b9c02ee3e7d023ccbe00bc891dcb843d6bfe7 Mon Sep 17 00:00:00 2001 From: Ian Davis <18375+iand@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:37:32 +0000 Subject: [PATCH 2/2] gofmt --- types.go | 120 +++++++++++++++++++++++++++---------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/types.go b/types.go index dd9b07c..a0a8ce5 100644 --- a/types.go +++ b/types.go @@ -64,57 +64,57 @@ type Trailer struct{} // together as husband, wife, and children, and contains family events // such as marriage, divorce, and census records. type FamilyRecord struct { - Xref string // Unique cross-reference identifier for this family (e.g., "@F1@") - Husband *IndividualRecord // Pointer to the husband/father individual - Wife *IndividualRecord // Pointer to the wife/mother individual - Child []*IndividualRecord // Pointers to child individuals - Event []*EventRecord // Family events (marriage, divorce, census, etc.) + Xref string // Unique cross-reference identifier for this family (e.g., "@F1@") + Husband *IndividualRecord // Pointer to the husband/father individual + Wife *IndividualRecord // Pointer to the wife/mother individual + Child []*IndividualRecord // Pointers to child individuals + Event []*EventRecord // Family events (marriage, divorce, census, etc.) NumberOfChildren string // Total number of children, may differ from len(Child) UserReference []*UserReferenceRecord // User-provided reference numbers AutomatedRecordId string // Unique record ID assigned by the source system Change ChangeRecord // Record of when this record was last modified Note []*NoteRecord // Notes attached to this family - Citation []*CitationRecord // Source citations for this family - Media []*MediaRecord // Media objects (photos, documents) for this family - UserDefined []UserDefinedTag // User-defined tags (prefixed with underscore) + Citation []*CitationRecord // Source citations for this family + Media []*MediaRecord // Media objects (photos, documents) for this family + UserDefined []UserDefinedTag // User-defined tags (prefixed with underscore) } // IndividualRecord represents a person in GEDCOM. It contains the person's // names, sex, life events, attributes, and links to their families. type IndividualRecord struct { - Xref string // Unique cross-reference identifier (e.g., "@I1@") - Name []*NameRecord // Names (may have multiple for maiden names, aliases) - Sex string // Sex: "M" for male, "F" for female, "U" for unknown - Event []*EventRecord // Life events (birth, death, burial, etc.) - Attribute []*EventRecord // Attributes (occupation, residence, education, etc.) - Parents []*FamilyLinkRecord // Links to families where this person is a child - Family []*FamilyLinkRecord // Links to families where this person is a spouse - Submitter []*SubmitterRecord // Submitters of this record - Association []*AssociationRecord // Associations with other individuals - PermanentRecordFileNumber string // Permanent record file number + Xref string // Unique cross-reference identifier (e.g., "@I1@") + Name []*NameRecord // Names (may have multiple for maiden names, aliases) + Sex string // Sex: "M" for male, "F" for female, "U" for unknown + Event []*EventRecord // Life events (birth, death, burial, etc.) + Attribute []*EventRecord // Attributes (occupation, residence, education, etc.) + Parents []*FamilyLinkRecord // Links to families where this person is a child + Family []*FamilyLinkRecord // Links to families where this person is a spouse + Submitter []*SubmitterRecord // Submitters of this record + Association []*AssociationRecord // Associations with other individuals + PermanentRecordFileNumber string // Permanent record file number AncestralFileNumber string // Ancestral file number UserReference []*UserReferenceRecord // User-provided reference numbers AutomatedRecordId string // Unique record ID assigned by the source system Change ChangeRecord // Record of when this record was last modified Note []*NoteRecord // Notes attached to this individual - Citation []*CitationRecord // Source citations for this individual - Media []*MediaRecord // Media objects (photos, documents) - UserDefined []UserDefinedTag // User-defined tags (prefixed with underscore) + Citation []*CitationRecord // Source citations for this individual + Media []*MediaRecord // Media objects (photos, documents) + UserDefined []UserDefinedTag // User-defined tags (prefixed with underscore) } // MediaRecord represents a multimedia object such as a photo, document, // or audio/video recording. It can be referenced by individuals, families, // events, and sources. type MediaRecord struct { - Xref string // Unique cross-reference identifier (e.g., "@M1@") - File []*FileRecord // File references for this media object + Xref string // Unique cross-reference identifier (e.g., "@M1@") + File []*FileRecord // File references for this media object Title string // Title or description of the media UserReference []*UserReferenceRecord // User-provided reference numbers AutomatedRecordId string // Unique record ID assigned by the source system Change ChangeRecord // Record of when this record was last modified Note []*NoteRecord // Notes attached to this media - Citation []*CitationRecord // Source citations - UserDefined []UserDefinedTag // User-defined tags + Citation []*CitationRecord // Source citations + UserDefined []UserDefinedTag // User-defined tags } // FileRecord contains information about a multimedia file. @@ -142,9 +142,9 @@ type ChangeRecord struct { // RepositoryRecord represents a repository where source documents are held, // such as a library, archive, or private collection. type RepositoryRecord struct { - Xref string // Unique cross-reference identifier (e.g., "@R1@") - Name string // Name of the repository - Address AddressRecord // Address of the repository + Xref string // Unique cross-reference identifier (e.g., "@R1@") + Name string // Name of the repository + Address AddressRecord // Address of the repository Note []*NoteRecord // Notes about the repository UserReference []*UserReferenceRecord // User-provided reference numbers AutomatedRecordId string // Unique record ID assigned by the source system @@ -167,8 +167,8 @@ type SourceRecord struct { AutomatedRecordId string // Unique record ID assigned by the source system Change ChangeRecord // Record of when this record was last modified Note []*NoteRecord // Notes about the source - Media []*MediaRecord // Media objects (photos of documents, etc.) - UserDefined []UserDefinedTag // User-defined tags + Media []*MediaRecord // Media objects (photos of documents, etc.) + UserDefined []UserDefinedTag // User-defined tags } // SourceDataRecord contains data recorded from a source. @@ -185,9 +185,9 @@ type SourceEventRecord struct { // SourceRepositoryRecord links a source to its repository. type SourceRepositoryRecord struct { - Repository *RepositoryRecord // The repository holding the source - Note []*NoteRecord // Notes about the source at this repository - CallNumber []*SourceCallNumberRecord // Call numbers for locating the source + Repository *RepositoryRecord // The repository holding the source + Note []*NoteRecord // Notes about the source at this repository + CallNumber []*SourceCallNumberRecord // Call numbers for locating the source } // SourceCallNumberRecord contains a call number for a source in a repository. @@ -217,10 +217,10 @@ type SubmitterRecord struct { Address *AddressRecord // Address of the submitter Media []*MediaRecord // Media objects (e.g., photo of submitter) Language []string // Languages used by the submitter - SubmitterRecordFileID string // Submitter record file identifier - AutomatedRecordId string // Unique record ID assigned by the source system - Note []*NoteRecord // Notes from the submitter - Change *ChangeRecord // Record of when this record was last modified + SubmitterRecordFileID string // Submitter record file identifier + AutomatedRecordId string // Unique record ID assigned by the source system + Note []*NoteRecord // Notes from the submitter + Change *ChangeRecord // Record of when this record was last modified } // NameRecord represents a name for an individual. An individual may have @@ -270,23 +270,23 @@ type DataRecord struct { // Common attribute tags include OCCU (occupation), RESI (residence), // EDUC (education), RELI (religion). type EventRecord struct { - Tag string // Event type tag (e.g., "BIRT", "DEAT", "MARR") - Value string // Event value, often "Y" to indicate event occurred - Type string // Detailed event type for generic EVEN tags - Date string // Date in GEDCOM date format - Place PlaceRecord // Location where the event occurred - Address AddressRecord // Address associated with the event - Age string // Age of the individual at the time of the event - ResponsibleAgency string // Agency responsible for the record - ReligiousAffiliation string // Religious affiliation associated with event - Cause string // Cause (e.g., cause of death) - RestrictionNotice string // Privacy restriction (GEDCOM 5.5.1) - ChildInFamily *FamilyRecord // Link to parent family for birth events - AdoptedByParent string // For adoption: "HUSB", "WIFE", or "BOTH" + Tag string // Event type tag (e.g., "BIRT", "DEAT", "MARR") + Value string // Event value, often "Y" to indicate event occurred + Type string // Detailed event type for generic EVEN tags + Date string // Date in GEDCOM date format + Place PlaceRecord // Location where the event occurred + Address AddressRecord // Address associated with the event + Age string // Age of the individual at the time of the event + ResponsibleAgency string // Agency responsible for the record + ReligiousAffiliation string // Religious affiliation associated with event + Cause string // Cause (e.g., cause of death) + RestrictionNotice string // Privacy restriction (GEDCOM 5.5.1) + ChildInFamily *FamilyRecord // Link to parent family for birth events + AdoptedByParent string // For adoption: "HUSB", "WIFE", or "BOTH" Citation []*CitationRecord // Source citations for this event - Media []*MediaRecord // Media objects (e.g., photos, certificates) - Note []*NoteRecord // Notes about this event - UserDefined []UserDefinedTag // User-defined tags + Media []*MediaRecord // Media objects (e.g., photos, certificates) + Note []*NoteRecord // Notes about this event + UserDefined []UserDefinedTag // User-defined tags } // NoteRecord contains a note or comment attached to a record. @@ -298,13 +298,13 @@ type NoteRecord struct { // PlaceRecord represents a geographic location. The Name field typically // contains a comma-separated jurisdiction hierarchy (e.g., "City, County, State, Country"). type PlaceRecord struct { - Name string // Place name (jurisdiction hierarchy) - Phonetic []*VariantPlaceNameRecord // Phonetic variants of the place name - Romanized []*VariantPlaceNameRecord // Romanized variants of the place name - Latitude string // Latitude in GEDCOM format (e.g., "N50.9333") - Longitude string // Longitude in GEDCOM format (e.g., "W1.8") - Citation []*CitationRecord // Source citations - Note []*NoteRecord // Notes about the place + Name string // Place name (jurisdiction hierarchy) + Phonetic []*VariantPlaceNameRecord // Phonetic variants of the place name + Romanized []*VariantPlaceNameRecord // Romanized variants of the place name + Latitude string // Latitude in GEDCOM format (e.g., "N50.9333") + Longitude string // Longitude in GEDCOM format (e.g., "W1.8") + Citation []*CitationRecord // Source citations + Note []*NoteRecord // Notes about the place } // VariantPlaceNameRecord represents a phonetic or romanized variant of a place name.