From cd7c4baaafd46fe165e6c561bb6e881e2429cc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Barga=C5=84ski?= Date: Fri, 22 Dec 2023 20:35:38 +0100 Subject: [PATCH] Add: OPF file supports multiple series as sequence of : calibre:series and calibre:series_index; including tests --- server/scanner/OpfFileScanner.js | 7 +- server/utils/parsers/parseOpfMetadata.js | 24 ++++-- .../utils/parsers/parseOpfMetadata.test.js | 85 +++++++++++++++++++ 3 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 test/server/utils/parsers/parseOpfMetadata.test.js diff --git a/server/scanner/OpfFileScanner.js b/server/scanner/OpfFileScanner.js index abc2540a..87c4f565 100644 --- a/server/scanner/OpfFileScanner.js +++ b/server/scanner/OpfFileScanner.js @@ -32,11 +32,8 @@ class OpfFileScanner { bookMetadata.narrators = opfMetadata.narrators } } else if (key === 'series') { - if (opfMetadata.series) { - bookMetadata.series = [{ - name: opfMetadata.series, - sequence: opfMetadata.sequence || null - }] + if (opfMetadata.series?.length) { + bookMetadata.series = opfMetadata.series } } else if (opfMetadata[key] && key !== 'sequence') { bookMetadata[key] = opfMetadata[key] diff --git a/server/utils/parsers/parseOpfMetadata.js b/server/utils/parsers/parseOpfMetadata.js index d5fb4651..4c057197 100644 --- a/server/utils/parsers/parseOpfMetadata.js +++ b/server/utils/parsers/parseOpfMetadata.js @@ -100,13 +100,20 @@ function fetchLanguage(metadata) { } function fetchSeries(metadataMeta) { - if (!metadataMeta) return null - return fetchTagString(metadataMeta, "calibre:series") -} - -function fetchVolumeNumber(metadataMeta) { - if (!metadataMeta) return null - return fetchTagString(metadataMeta, "calibre:series_index") + if (!metadataMeta) return [] + const result = [] + for (let i = 0; i < metadataMeta.length; i++) { + if (metadataMeta[i].$.name === "calibre:series") { + const name = metadataMeta[i].$.content + let sequence = null + if (i + 1 < metadataMeta.length && + metadataMeta[i + 1].$.name === "calibre:series_index" && metadataMeta[i + 1].$.content) { + sequence = metadataMeta[i + 1].$.content + } + result.push({ name, sequence }) + } + } + return result } function fetchNarrators(creators, metadata) { @@ -173,8 +180,7 @@ module.exports.parseOpfMetadataXML = async (xml) => { description: fetchDescription(metadata), genres: fetchGenres(metadata), language: fetchLanguage(metadata), - series: fetchSeries(metadata.meta), - sequence: fetchVolumeNumber(metadata.meta), + series: fetchSeries(metadataMeta), tags: fetchTags(metadata) } return data diff --git a/test/server/utils/parsers/parseOpfMetadata.test.js b/test/server/utils/parsers/parseOpfMetadata.test.js new file mode 100644 index 00000000..c0732273 --- /dev/null +++ b/test/server/utils/parsers/parseOpfMetadata.test.js @@ -0,0 +1,85 @@ +const chai = require('chai') +const expect = chai.expect +const { parseOpfMetadataXML } = require('../../../../server/utils/parsers/parseOpfMetadata') + + +describe('parseOpfMetadata - test series', async () => { + it('test one serie', async() => { + const opf = ` + + + + + + + + ` + const parsedOpf = await parseOpfMetadataXML(opf) + expect(parsedOpf.series).to.deep.equal([{"name": "Serie","sequence": "1"}]) + }) + + it('test more then 1 serie - in correct order', async() => { + const opf = ` + + + + + + + + + + + + ` + const parsedOpf = await parseOpfMetadataXML(opf) + expect(parsedOpf.series).to.deep.equal([ + {"name": "Serie 1","sequence": "1"}, + {"name": "Serie 2","sequence": "2"}, + {"name": "Serie 3","sequence": "3"}, + ]) + }) + + it('test messed order of series content and index', async() => { + const opf = ` + + + + + + + + + + + ` + const parsedOpf = await parseOpfMetadataXML(opf) + expect(parsedOpf.series).to.deep.equal([ + {"name": "Serie 1","sequence": "1"}, + {"name": "Serie 3","sequence": null}, + ]) + }) + + it('test different values of series content and index', async() => { + const opf = ` + + + + + + + + + + + + ` + const parsedOpf = await parseOpfMetadataXML(opf) + // console.log(JSON.stringify(parsedOpf, null, 4)) + expect(parsedOpf.series).to.deep.equal([ + {"name": "Serie 1", "sequence": null}, + {"name": "Serie 2", "sequence": "abc"}, + {"name": "Serie 3", "sequence": null}, + ]) + }) +})