rootsdev / gedcomx-js

JavaScript library for GEDCOM X
http://rootsdev.org/gedcomx-js/
MIT License
10 stars 1 forks source link
gedcomx genealogy

GEDCOM X JS

npm Build Status codecov Scrutinizer Code Quality

A JavaScript library for the GEDCOM X data model including the GEDCOM X RS, the GEDCOM X Records, and the GEDCOM X Atom Extensions specifications.

Read the documentation for a list of all classes and methods.

Install

NPM

npm install --save gedcomx-js

CDN via unpkg

<script src="https://unpkg.com/gedcomx-js@2.5.1/dist/gedcomx.min.js"></script>

In the browser, gedcomx-js is attached to the window as a global named GedcomX.

Usage

Create a document from a JSON object.

var doc = new GedcomX({
  persons: [
    {
      id: 'person1',
      facts: [
        {
          type: 'http://gedcomx.org/Birth',
          date: {
            formal: '+2014-04-09'
          },
          place: {
            original: 'Verona'
          }
        }
      ]
    }
  ]
});

Or build a document from scratch.

var doc = new GedcomX()
  .addPerson(
    new GedcomX.Person()
      .addFact(
        new GedcomX.Fact()
          .setType('http://gedcomx.org/Birth')
          .setDate(new GedcomX.Date().setFormal('+2014-04-09'))
          .setPlace(new GedcomX.PlaceReference().setOriginal('Verona'))
      )
  );

Or mix and match.

var doc = new GedcomX({
  persons: [
    new GedcomX.Person({
      facts: [
        new GedcomX.Fact()
          .setType('http://gedcomx.org/Birth')
          .setDate({ formal: '+2014-04-09' })
          .setPlace({ original: 'Verona' })
      ]
    })
  ]
});

RS Spec, Records Spec, and Atom Extensions

The RS, Records, and Atom extensions are disabled by default. They must be explicitly enabled.

GedcomX.enableRsExtensions();
GedcomX.enableRecordsExtensions();
GedcomX.enableAtomExtensions();

Note that the Atom extensions depend on the RS extensions thus calling enableAtomExtensions() will also call enableRsExtensions().

Installation

npm install gedcomx-js

Notes

The use of new when constructing objects is optional. The two following lines of code are equivalent:

new GedcomX.Person();
GedcomX.Person();

All objects have a toJSON() method for serialization.

The library is currently just an anemic domain model for the GEDCOM X JSON Serialization Format. We plan on eventually adding useful helpers and better enforcement of the specification (such as checking the format of formal dates).

You can add helpers of your own. Perhaps you're working with a data set where people only have one name with no prefix or suffix. You'll end up doing this often:

person.addName(
  GedcomX.Name()
    .addNameForm(
      GedcomX.NameForm()
        .addNamePart(
          GedcomX.NamePart()
            .setType('http://gedcomx.org/Given')
            .setValue('Jonathan')
          )
        .addNamePart(
          GedcomX.NamePart()
            .setType('http://gedcomx.org/Surname')
            .setValue('Burrows')
        )
    )
);

That's a lot of work for one name. So you could create your own helper method by adding to the GedcomX.Person prototype.

GedcomX.Person.prototype.addSimpleName = function(given, surname){
  this.addName(
    GedcomX.Name()
      .addNameForm(
        GedcomX.NameForm()
          .addNamePart(
            GedcomX.NamePart()
              .setType('http://gedcomx.org/Given')
              .setValue(given)
          )
          .addNamePart(
            GedcomX.NamePart()
              .setType('http://gedcomx.org/Surname')
              .setValue(surname)
          )
      )
  )
};

Then adding names is easy:

person.addSimpleName('Jonathan', 'Burrows');

Data Model Extensions

GEDCOM X allows for it's data model to be extended. The RS and Records specs are defined as extensions.

There are two ways that the spec can be extended.

1. Adding Properties to Existing Data Types

Extensions can add properties to existing data types. For example the RS spec defines resourceId as an extension to ResourceReference. gedcomx-js supports property extensions by using prototypical inheritance which allows for prototypes to be modified.

There are three situations where extensions need to be accounted for:

  1. Deserialization and Instantiation: All classes have an init() method which can me overriden to account for additional properties.

    // Override init() so that we can deserialize normalized values
    var oldInit = GedcomX.ResourceReference.prototype.init;
    GedcomX.ResourceReference.prototype.init = function(json){
      oldInit.call(this, json);
      if(json){
        this.setResourceId(json.resourceId);
      }
    };
  2. Getters and Setters: Just extend the prototype.

    /**
     * Set the resourceId
     * 
     * @param {Boolean} resourceId
     * @return {ResourceReference} this
     */
    GedcomX.ResourceReference.prototype.setResourceId = function(resourceId){
      this.resourceId = resourceId;
      return this;
    };
    
    /**
     * Get the resourceId
     * 
     * @return {Boolean} resourceId
     */
    GedcomX.ResourceReference.prototype.getResourceId = function(){
      return this.resourceId;
    };
  3. Serialization: Each class has a static jsonProps attribute which is a list of properties that should be serialized.

    // Extend serialization properties
    GedcomX.ResourceReference.jsonProps.push('resourceId');

    Not only does it support extensibility but it also great reduces code duplication.

2. Adding New Data Types

New data types are added by setting a reference on the exported GedcomX object.

var DisplayProperties = function(json){
  // Constructor
};

// Lots of prototype setup...

// Add to the GedcomX object
GedcomX.DisplayProperties = DisplayProperties;

Next we need to configure when our new data type will be used. The example above uses DisplayProperties which is defined in the RS spec as being an extension of Person. Thus we also must follow the method described above for adding the new property display to the existing data type Person.