diff --git a/src/helpers.js b/src/helpers.js index 2811c5b..259215b 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -46,7 +46,7 @@ const createNoteValue = (k, v, sep = ' --- ') => { } const createValue = (k, v) => { - if (!v) return + if (!v) return {} switch (k) { case (`${TROPY}#note`): return createNoteValue(k, v) @@ -90,7 +90,10 @@ function getProtocolAndPath(path, relativeTo) { } } const parseProtocol = (photo, baseDirectory) => { - const rawPath = photo[`${TROPY}#path`][0]['@value'] + const rawPath = photo[`${TROPY}#path`]?.[0]['@value'] + if (!rawPath) { + return photo + } const { protocol, path } = getProtocolAndPath(rawPath, baseDirectory) photo[`${TROPY}#path`][0]['@value'] = path Object.assign(photo, createValue(`${TROPY}#protocol`, protocol)) diff --git a/src/plugin.js b/src/plugin.js index 5c054d6..51162bb 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -204,8 +204,15 @@ class CSVPlugin { let photoData = Object.assign( ...p.map((v, idx) => createValue(photoKeys[idx], v)) ) - parseProtocol(photoData, baseDirectory) - item.photo.push(addTemplateKey(photoData, this.options.photoTemplate)) + if (photoData[`${TROPY}#path`] !== undefined) { + parseProtocol(photoData, baseDirectory) + item.photo.push( + addTemplateKey(photoData, this.options.photoTemplate) + ) + } else { + // Don't fail if there's no TROPY/#path values for that row + console.warn('No photo paths parsed for row', row) + } } } return item @@ -225,10 +232,12 @@ class CSVPlugin { for (const file of files) { try { - const csvRows = parse( - await readFile(file), - { relaxColumnCount: true, delimiter: this.options.delimiter } - ) + const csvRows = parse(await readFile(file), { + relaxColumnCount: true, + delimiter: this.options.delimiter, + bom: true, + skipEmptyLines: true + }) const headerRow = this.options.customHeaders ? parse(this.options.customHeaders, { delimiter: this.options.delimiter } diff --git a/test/import_row_test.js b/test/import_row_test.js index 68782c0..5ed7dcc 100644 --- a/test/import_row_test.js +++ b/test/import_row_test.js @@ -15,7 +15,7 @@ const photoHeaders = [ `${TROPY}#note` ] const rowNoPhoto = ['2022-01-02', 'title', ''] -const rowNoTitle = ['2022-01-02', '', ''] +const rowNoDate = ['', 'title', ''] const rowSinglePhoto = [ '2022-01-03', 'title1', @@ -31,6 +31,17 @@ const rowManyPhoto = [ (platform === 'win32') ? 'D:\\user\\photo2.jpg' : '/home/user/photo2.jpg', 'some note --- another note, with a comma'] +const rowMissingPhoto = [ + '2022-01-04', + 'title2', + 'tag2', + (platform === 'win32') ? 'D:\\user\\photo1.jpg' : '/home/user/photo1.jpg', + 'a note', + (platform === 'win32') ? 'D:\\user\\photo2.jpg' : '/home/user/photo2.jpg', + 'some note --- another note, with a comma', + // No photo path provided + '', 'this note should be dropped?'] + function generatePhoto(path, note = null, protocol = 'file') { const photo = { 'https://tropy.org/v1/tropy#path': [{ '@value': path }], @@ -62,9 +73,9 @@ describe('Parse row', () => { assert.deepEqual(actual, generateExpectedItem(rowNoPhoto[0], rowNoPhoto[1])) }) it('Does not add key to item if value is empty in csv', () => { - const actual = plugin.parseRow(rowNoTitle, itemHeaders, photoHeaders) - assert.equal(actual['http://purl.org/dc/terms/title'], undefined) - assert.ok(actual['http://purl.org/dc/elements/1.1/date'] !== undefined) + const actual = plugin.parseRow(rowNoDate, itemHeaders, photoHeaders) + assert.ok(actual['http://purl.org/dc/terms/title'] !== undefined) + assert.equal(actual['http://purl.org/dc/elements/1.1/date'], undefined) }) it('Item has no photos if no photo headers present', () => { const actual = plugin.parseRow(rowSinglePhoto, itemHeaders, undefined) @@ -82,6 +93,14 @@ describe('Parse row', () => { assert.deepEqual(actual['photo'][0], generatePhoto(rowManyPhoto[3], rowManyPhoto[4])) }) + it('Photo and note not imported if no path for photos', () => { + const actual = plugin.parseRow(rowMissingPhoto, itemHeaders, photoHeaders) + assert.equal(actual.photo.length, 2) + assert.equal( + JSON.stringify(actual).includes('This note should be dropped?'), + false + ) + }) it('Photo has no notes if notes not present in CSV', () => { const actual = plugin.parseRow(rowSinglePhoto, itemHeaders, photoHeaders) assert.equal(actual.photo.length, 1)