Skip to content

Commit ec73cab

Browse files
committed
initial to-JSON dump
1 parent 5edcf4e commit ec73cab

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

xto70.js

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@
7575
*
7676
* @param {object} gx - the a GEDOMX dataset parsed from JSON format
7777
* @param {function} error - a vararg function accepting error messages; for example, `console.error`
78+
* @param {string} format - `text/json` if want prototype g7 JSON; otherwise get GEDCOM string
7879
* @returns {string} a corresponding GEDCOM 7.0 dataset
7980
*/
80-
function GEDCOMXTo7(gx, error) {
81+
function GEDCOMXTo7(gx, error, format) {
8182

8283
if (!error) error = (...args) => {}
8384
const xlinks = {}
@@ -96,11 +97,13 @@ function GEDCOMXTo7(gx, error) {
9697
this.tag = tag
9798
this.id = null
9899
this.payload = payload
99-
if (payload && 'object' == typeof payload) {
100+
if (payload === null) {
101+
this.payload = null
102+
} else if (payload && 'object' == typeof payload) {
100103
this.payload = payload
101104
if (!payload.id) this.payload.id = 'X'+(g7s.nextXrefID += 1)
102105
} else if (payload) this.payload = String(payload).replace(/\r\n?/g, '\n')
103-
else this.payload = null
106+
else this.payload = undefined
104107
this.subs = substructures.filter(x=>x)
105108
}
106109
g7s.nextXrefID = 0
@@ -109,7 +112,7 @@ function GEDCOMXTo7(gx, error) {
109112
let self = level + (this.id ? ' @'+this.id+'@':'') + ' '+this.tag
110113
if (this.payload && 'object' == typeof this.payload) {
111114
self += ' @'+this.payload.id+'@'
112-
} else if (this.payload == '@VOID@') {
115+
} else if (this.payload === null) {
113116
self += ' @VOID@'
114117
} else if (this.payload) {
115118
let txt = this.payload.replace(/\n(@?)/g, `\n${level+1} CONT $1$1`).replace(/^([0-9]+ CONT) $/mg, "$1")
@@ -119,6 +122,15 @@ function GEDCOMXTo7(gx, error) {
119122
}
120123
return self+'\n'+this.subs.map(s => s.toString(level+1)).join('')
121124
}
125+
g7s.prototype.toJSO = function() {
126+
const ans = {'tag':this.tag}
127+
if (this.id) ans.id = this.id
128+
if (this.payload === null) ans.pointer = null
129+
else if ('object' == typeof this.payload) ans.pointer = '#'+this.payload.id
130+
else if ('string' == typeof this.payload) ans.text = this.payload
131+
if (this.subs.length > 0) ans.subs = this.subs.map(x=>x.toJSO())
132+
return ans
133+
}
122134
g7s.prototype.add = function(...subs) { this.subs.push(...subs.filter(x=>x)) }
123135

124136
const parseDataURL = uri => {
@@ -131,7 +143,7 @@ function GEDCOMXTo7(gx, error) {
131143

132144

133145
let records = {}
134-
let header = g7s('HEAD', null, g7s('GEDC',null, g7s('VERS','7.0')))
146+
let header = g7s('HEAD', undefined, g7s('GEDC',undefined, g7s('VERS','7.0')))
135147
let extensions = []
136148
let trailer = g7s('TRLR')
137149

@@ -167,12 +179,12 @@ function GEDCOMXTo7(gx, error) {
167179
return ans
168180
}
169181
if ('original' in d) {
170-
return g7s('DATE', null, g7s('PHRASE', d.original))
182+
return g7s('DATE', undefined, g7s('PHRASE', d.original))
171183
} else return null
172184
}
173185
let bits = d.split('/')
174186
let phrases = []
175-
if (bits.length > 3) return g7s('DATE',null,g7s('PHRASE','unsupported gedcomx data: '+d))
187+
if (bits.length > 3) return g7s('DATE',undefined,g7s('PHRASE','unsupported gedcomx data: '+d))
176188
if (bits.length == 3) {
177189
// recurring
178190
let times = bits[0].substr(1)
@@ -281,12 +293,12 @@ function GEDCOMXTo7(gx, error) {
281293
}
282294
if (kml) {
283295
if (!(kml in records)) {
284-
records[kml] = g7s('OBJE',null,g7s('FILE',kml, g7s('MEDI','application/vnd.google-earth.kml+xml')))
296+
records[kml] = g7s('OBJE',undefined,g7s('FILE',kml, g7s('MEDI','application/vnd.google-earth.kml+xml')))
285297
}
286298
ans.add(g7s('_OBJE', records[kml]))
287299
}
288300
if (map) {
289-
ans.add(g7s('MAP',null,
301+
ans.add(g7s('MAP',undefined,
290302
g7s('LATI',(map.latitude<0?'S':'N')+Math.abs(map.latitude)),
291303
g7s('LONG',(map.longitude<0?'W':'E')+Math.abs(map.longitude)),
292304
))
@@ -382,7 +394,7 @@ function GEDCOMXTo7(gx, error) {
382394

383395
/** INDI records */
384396
const doPerson = p => {
385-
let me = records['#'+p.id] || g7s('INDI', null, g7s('EXID', p.id, g7s('TYPE','https://gedcom.io/exid-type/FamilySearch-PersonId')))
397+
let me = records['#'+p.id] || g7s('INDI', undefined, g7s('EXID', p.id, g7s('TYPE','https://gedcom.io/exid-type/FamilySearch-PersonId')))
386398
let modified = 0
387399
let didLiving = false
388400

@@ -431,7 +443,7 @@ function GEDCOMXTo7(gx, error) {
431443
if (p.living === false) me.add(g7s('DEAT', 'Y'))
432444
else if (p.living) me.add(g7s('NO','DEAT'))
433445
}
434-
if (modified) me.add(g7s('CHAN',null,doDate(modified)))
446+
if (modified) me.add(g7s('CHAN',undefined,doDate(modified)))
435447
records['#'+p.id] = me
436448
me.resourceId = p.id // not displayed, just for local interlinks
437449
}
@@ -440,7 +452,7 @@ function GEDCOMXTo7(gx, error) {
440452
const makeOrFindFam = (p1,p2) => {
441453
let id = [p1?.resourceId,p2?.resourceId].sort().join('+')
442454
if (id in records) return records[id]
443-
let ans = g7s('FAM',null,
455+
let ans = g7s('FAM',undefined,
444456
p1?g7s('HUSB', records['#'+p1.resourceId]):null,
445457
p2?g7s('WIFE', records['#'+p2.resourceId]):null,
446458
)
@@ -548,7 +560,7 @@ function GEDCOMXTo7(gx, error) {
548560
ans = g7s(atags[f.type], f.value)
549561
if (ans.tag == 'IDNO') ans.add(g7s('TYPE','Unspecified')) // fix me: figure out why no NationalId fields have nations in FS data I've seen
550562
} else if (f.type in evens) {
551-
ans = g7s('EVEN', null, g7s('TYPE', evens[f.type]))
563+
ans = g7s('EVEN', undefined, g7s('TYPE', evens[f.type]))
552564
if (f.value) ans.add(g7s('NOTE', f.value))
553565
} else if (f.type in facts) {
554566
ans = g7s('FACT', f.value, g7s('TYPE', facts[f.type]))
@@ -607,7 +619,7 @@ function GEDCOMXTo7(gx, error) {
607619
} else if (f.type in atags) {
608620
ans = g7s(atags[f.type], f.value)
609621
} else if (f.type in evens) {
610-
ans = g7s('EVEN', null, g7s('TYPE', evens[f.type]))
622+
ans = g7s('EVEN', undefined, g7s('TYPE', evens[f.type]))
611623
if (f.value) ans.add(g7s('NOTE', f.value))
612624
} else if (f.type in facts) {
613625
ans = g7s('FACT', f.value, g7s('TYPE', facts[f.type]))
@@ -638,9 +650,9 @@ function GEDCOMXTo7(gx, error) {
638650
const doRelationship1 = r => {
639651
if (r.type != 'http://gedcomx.org/Couple') return
640652
if (!('#'+r.person1.resourceId in records))
641-
records['#'+r.person1.resourceId] = g7s('INDI',null,g7s('EXID',r.person1.resourceId,g7s('TYPE','https://gedcom.io/exid-type/FamilySearch-PersonId')))
653+
records['#'+r.person1.resourceId] = g7s('INDI',undefined,g7s('EXID',r.person1.resourceId,g7s('TYPE','https://gedcom.io/exid-type/FamilySearch-PersonId')))
642654
if (!('#'+r.person2.resourceId in records))
643-
records['#'+r.person2.resourceId] = g7s('INDI',null,g7s('EXID',r.person2.resourceId,g7s('TYPE','https://gedcom.io/exid-type/FamilySearch-PersonId')))
655+
records['#'+r.person2.resourceId] = g7s('INDI',undefined,g7s('EXID',r.person2.resourceId,g7s('TYPE','https://gedcom.io/exid-type/FamilySearch-PersonId')))
644656
let id = [r.person1.resourceId,r.person2.resourceId].sort().join('+')
645657
let fam = makeOrFindFam(r.person1, r.person2)
646658
fam.add(g7s('EXID', r.id, g7s('TYPE', 'https://gedcom.io/exid-type/FamilySearch-RelationshipId'))) // FIX ME: register this type
@@ -692,13 +704,13 @@ function GEDCOMXTo7(gx, error) {
692704
for(let i=0; i<fam.subs.length; i+=1) if (fam.subs[i].tag == 'CHIL') {
693705
chilnum -= 1
694706
if (chilnum == 0) {
695-
if (fam.subs[i].payload == '@VOID@') fam.subs[i].payload = per
707+
if (fam.subs[i].payload === null) fam.subs[i].payload = per
696708
else fam.subs.splice(i,0,g7s('CHIL',per))
697709
break
698710
}
699711
}
700712
if (chilnum > 0) {
701-
while(chilnum > 1) { fam.add(g7s('CHIL','@VOID@')); chilnum -= 1; }
713+
while(chilnum > 1) { fam.add(g7s('CHIL',null)); chilnum -= 1; }
702714
fam.add(g7s('CHIL',per))
703715
}
704716
}
@@ -739,6 +751,7 @@ function GEDCOMXTo7(gx, error) {
739751

740752

741753

742-
if (extensions) header.add(g7s('SCHMA',null, ...extensions))
754+
if (extensions.length > 0) header.add(g7s('SCHMA',undefined, ...extensions))
755+
if (format == 'text/json') return [header.toJSO()].concat(Object.values(records).map(x=>x.toJSO()))
743756
return header + Object.values(records).join('') + trailer
744757
}

0 commit comments

Comments
 (0)