diff --git a/bids-validator-web/package.json b/bids-validator-web/package.json index 3f77e0643..75dd8310d 100644 --- a/bids-validator-web/package.json +++ b/bids-validator-web/package.json @@ -5,6 +5,7 @@ "main": "index.js", "license": "MIT", "dependencies": { + "@babel/runtime": "^7.16.7", "bootstrap": "^4.3.0", "bowser": "^1.0.0", "next": "^11.1.2", diff --git a/bids-validator/bin/bids-validator b/bids-validator/bin/bids-validator index 65840cd95..e5221accf 100755 --- a/bids-validator/bin/bids-validator +++ b/bids-validator/bin/bids-validator @@ -8,6 +8,7 @@ function entry(cli) { try { // Test if there's a development tree to run require.resolve('../cli.js') + process.env.ESBUILD_MAX_BUFFER = 64 * 1024 * 1024 // For dev, use esbuild-runner require('esbuild-runner/register') const { default: cli } = require('../cli.js') diff --git a/bids-validator/package.json b/bids-validator/package.json index a01350336..054da6d47 100644 --- a/bids-validator/package.json +++ b/bids-validator/package.json @@ -58,7 +58,9 @@ "stream-browserify": "^3.0.0", "table": "^5.2.3", "yaml": "^1.10.2", - "yargs": "^16.2.0" + "yargs": "^16.2.0", + "exifreader": "^4.1.0", + "xml2js": "^0.4.23" }, "devDependencies": { "adm-zip": "", diff --git a/bids-validator/tests/tsv.spec.js b/bids-validator/tests/tsv.spec.js index ef94134d2..9a477f75f 100644 --- a/bids-validator/tests/tsv.spec.js +++ b/bids-validator/tests/tsv.spec.js @@ -685,4 +685,30 @@ describe('TSV', function() { let issues = validate.TSV.validateContRec([physio_file], {}) assert(issues.length === 1 && issues[0].code === 133) }) + + // samples checks ----------------------------------------------------------- + + const samplesFile = { + name: 'samples.tsv', + relativePath: '/samples.tsv', + } + + it('should return errors for each missing mandatory header in samples.tsv', () => { + const tsv = 'wrong_col\nsome_data\n' + validate.TSV.TSV(samplesFile, tsv, [], function(issues) { + expect(issues.length).toBe(3) + const codes = issues.map(x => x.code) + expect(codes.includes(216)).toBe(true) + expect(codes.includes(217)).toBe(true) + expect(codes.includes(218)).toBe(true) + }) + }) + + it('should return an error for invalid sample_type samples.tsv', () => { + const tsv = 'sample_type\nbad\n' + validate.TSV.TSV(samplesFile, tsv, [], function(issues) { + const codes = issues.map(x => x.code) + expect(codes.includes(219)).toBe(true) + }) + }) }) diff --git a/bids-validator/utils/files/generateMergedSidecarDictWithPath.js b/bids-validator/utils/files/generateMergedSidecarDictWithPath.js deleted file mode 100644 index 78e9fbe01..000000000 --- a/bids-validator/utils/files/generateMergedSidecarDictWithPath.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Generate Merged Sidecar Dictionary - * - * Takes an array of potential sidecards and a - * master object dictionary of all JSON file - * content and returns a merged dictionary - * containing all values from the potential - * sidecars and the sidecarName - */ -function generateMergedSidecarDictWithPath(potentialSidecars, jsonContents) { - let mergedDictionary = {} - potentialSidecars.map(sidecarName => { - const jsonObject = jsonContents[sidecarName] - if (jsonObject) { - mergedDictionary['sidecarName'] = sidecarName - for (var key in jsonObject) { - mergedDictionary[key] = jsonObject[key] - } - } else if (jsonObject === null) { - mergedDictionary.invalid = true - } - }) - return mergedDictionary -} - -export default generateMergedSidecarDictWithPath diff --git a/bids-validator/utils/files/index.js b/bids-validator/utils/files/index.js index b93324da6..237b940aa 100644 --- a/bids-validator/utils/files/index.js +++ b/bids-validator/utils/files/index.js @@ -15,7 +15,6 @@ import illegalCharacterTest from './illegalCharacterTest' import sessions from './sessions' import remoteFiles from './remoteFiles' import getFileStats from './getFileStats' -import generateMergedSidecarDictWithPath from './generateMergedSidecarDictWithPath' // public API --------------------------------------------------------------------- @@ -28,7 +27,6 @@ export default { readOMEFile, readNiftiHeader, generateMergedSidecarDict, - generateMergedSidecarDictWithPath, potentialLocations, getBFileContent, collectDirectorySize, diff --git a/bids-validator/utils/files/readFile.js b/bids-validator/utils/files/readFile.js index b0efb9bff..4f420d6c7 100644 --- a/bids-validator/utils/files/readFile.js +++ b/bids-validator/utils/files/readFile.js @@ -25,7 +25,11 @@ const checkEncoding = (file, data, cb) => { } /** - * Read + * readFile + * @param {object | File} file - nodeJS fs file or browser File + * @param {boolean} annexed - is the file currently annexed? + * @param {string} dir - path to directory containing dataset. Only used if + * annexed is true. * * A helper method for reading file contents. * Takes a file object and a callback and calls @@ -39,12 +43,12 @@ const checkEncoding = (file, data, cb) => { function readFile(file, annexed, dir) { return new Promise((resolve, reject) => { if (isNode) { - testFile(file, annexed, dir, function (issue, stats, remoteBuffer) { + testFile(file, annexed, dir, function(issue, stats, remoteBuffer) { if (issue) { return reject(issue) } if (!remoteBuffer) { - fs.readFile(file.path, function (err, data) { + fs.readFile(file.path, function(err, data) { if (err) { return reject(err) } diff --git a/bids-validator/validators/bids/fullTest.js b/bids-validator/validators/bids/fullTest.js index 67061b534..41c4cff88 100644 --- a/bids-validator/validators/bids/fullTest.js +++ b/bids-validator/validators/bids/fullTest.js @@ -148,6 +148,7 @@ const fullTest = (fileList, options, annexed, dir, schema, callback) => { files, jsonContentsDict, ) + self.issues = self.issues .concat(samplesIssues) .concat(jsonAndFieldIssues) diff --git a/bids-validator/validators/microscopy/__tests__/checkJSONAndField.spec.js b/bids-validator/validators/microscopy/__tests__/checkJSONAndField.spec.js new file mode 100644 index 000000000..62fa586b5 --- /dev/null +++ b/bids-validator/validators/microscopy/__tests__/checkJSONAndField.spec.js @@ -0,0 +1,51 @@ +import { assert } from 'chai' +import checkJSONAndField from '../checkJSONAndField' + +describe('checkJSONAndField()', () => { + const emptyJsonContentsDict = { + 'test.json': {}, + } + it('returns no issues with empty arguments', () => { + const issues = checkJSONAndField({}, {}) + expect(issues.length).toBe(0) + }) + + it('returns issue 225 with no json for ome files', () => { + const files = { + ome: [{ relativePath: 'test.ome.tif' }], + } + const issues = checkJSONAndField(files, emptyJsonContentsDict) + expect(issues.length).toBe(1) + expect(issues[0].code).toBe(225) + }) + + it('returns issue 225 with no json for tif files', () => { + const files = { + tif: [{ relativePath: 'test.tif' }], + } + const issues = checkJSONAndField(files, emptyJsonContentsDict) + expect(issues.length).toBe(1) + expect(issues[0].code).toBe(225) + }) + + it('returns issue 225 with no json for png files', () => { + const files = { + png: [{ relativePath: 'test.png' }], + } + const issues = checkJSONAndField(files, emptyJsonContentsDict) + expect(issues.length).toBe(1) + expect(issues[0].code).toBe(225) + }) + + it('returns warning 223 if chunk entity present but missing metadata', () => { + const files = { + ome: [{ relativePath: '/test_chunk-01.ome.tif' }], + } + const jsonContentsDict = { + '/test_chunk-01.json': { testKey: 'testValue' }, + } + const issues = checkJSONAndField(files, jsonContentsDict) + expect(issues.length).toBe(1) + expect(issues[0].code).toBe(223) + }) +}) diff --git a/bids-validator/validators/microscopy/__tests__/checkSample.spec.js b/bids-validator/validators/microscopy/__tests__/checkSample.spec.js new file mode 100644 index 000000000..5dd541c27 --- /dev/null +++ b/bids-validator/validators/microscopy/__tests__/checkSample.spec.js @@ -0,0 +1,19 @@ +import checkSamples from '../checkSamples' +describe('checkSamples()', () => { + it('returns issue 214 when no samples.tsv is present', () => { + const fileList = { + '0': { relativePath: '/test.tsv' }, + } + const issues = checkSamples(fileList) + expect(issues.length).toBe(1) + expect(issues[0].code).toBe(214) + }) + + it('doesnt return issue 214 when samples.tsv is present', () => { + const fileList = { + '0': { relativePath: '/samples.tsv' }, + } + const issues = checkSamples(fileList) + expect(issues.length).toBe(0) + }) +}) diff --git a/bids-validator/validators/microscopy/__tests__/data/btif_id.ome.tif b/bids-validator/validators/microscopy/__tests__/data/btif_id.ome.tif new file mode 100644 index 000000000..f62946161 Binary files /dev/null and b/bids-validator/validators/microscopy/__tests__/data/btif_id.ome.tif differ diff --git a/bids-validator/validators/microscopy/__tests__/data/invalid_id.ome.tif b/bids-validator/validators/microscopy/__tests__/data/invalid_id.ome.tif new file mode 100644 index 000000000..96973db51 Binary files /dev/null and b/bids-validator/validators/microscopy/__tests__/data/invalid_id.ome.tif differ diff --git a/bids-validator/validators/microscopy/__tests__/data/tif_id.ome.btf b/bids-validator/validators/microscopy/__tests__/data/tif_id.ome.btf new file mode 100644 index 000000000..416a1d8ec Binary files /dev/null and b/bids-validator/validators/microscopy/__tests__/data/tif_id.ome.btf differ diff --git a/bids-validator/validators/microscopy/__tests__/data/tif_id.ome.tif b/bids-validator/validators/microscopy/__tests__/data/tif_id.ome.tif new file mode 100644 index 000000000..416a1d8ec Binary files /dev/null and b/bids-validator/validators/microscopy/__tests__/data/tif_id.ome.tif differ diff --git a/bids-validator/validators/microscopy/__tests__/data/valid.ome.tif b/bids-validator/validators/microscopy/__tests__/data/valid.ome.tif new file mode 100644 index 000000000..416a1d8ec Binary files /dev/null and b/bids-validator/validators/microscopy/__tests__/data/valid.ome.tif differ diff --git a/bids-validator/validators/microscopy/__tests__/validate.spec.js b/bids-validator/validators/microscopy/__tests__/validate.spec.js new file mode 100644 index 000000000..2bf7a59f2 --- /dev/null +++ b/bids-validator/validators/microscopy/__tests__/validate.spec.js @@ -0,0 +1,99 @@ +import path from 'path' + +import readDir from '../../../utils/files/readDir' +import validate from '../validate' + +const dataDir = path.join(__dirname, '/data') + +const jsonContent = { + Manufacturer: 'Miltenyi Biotec', + ManufacturersModelName: 'UltraMicroscope II', + BodyPart: 'CSPINE', + SampleEnvironment: 'ex vivo', + SampleFixation: '4% paraformaldehyde, 2% glutaraldehyde', + SampleStaining: 'Luxol fast blue', + PixelSize: [1, 1, 1], + PixelSizeUnits: 'um', + Immersion: 'Oil', + NumericalAperture: 1.4, + Magnification: 40, + ChunkTransformationMatrix: [ + [1, 0, 0, 0], + [0, 2, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + ], + ChunkTransformationMatrixAxis: ['X', 'Y', 'Z'], +} + +describe('validate', () => { + it('returns error 227 with extension/id mismatch', () => { + const fileName = 'btif_id.ome.tif' + const files = [ + { + name: fileName, + relativePath: `/bids-validator/validators/microscopy/__tests__/data/${fileName}`, + path: path.join(dataDir, fileName), + }, + ] + + expect.assertions(3) + return validate(files, {}).then(issues => { + expect(issues.length).toBe(2) + expect(issues[0].code).toBe(227) + expect(issues[1].code).toBe(226) + }) + }) + + it('returns error 227 with incorrect id in magic number', () => { + const fileName = 'invalid_id.ome.tif' + const files = [ + { + name: fileName, + relativePath: `/bids-validator/validators/microscopy/__tests__/data/${fileName}`, + path: path.join(dataDir, fileName), + }, + ] + expect.assertions(2) + return validate(files, {}).then(issues => { + expect(issues.length).toBe(1) + expect(issues[0].code).toBe(227) + }) + }) + + it('returns error 227 with tif id and btf extension', () => { + const fileName = 'tif_id.ome.btf' + const files = [ + { + name: fileName, + relativePath: `/bids-validator/validators/microscopy/__tests__/data/${fileName}`, + path: path.join(dataDir, fileName), + }, + ] + + expect.assertions(2) + return validate(files, {}).then(issues => { + expect(issues.length).toBe(1) + expect(issues[0].code).toBe(227) + }) + }) + + it('validates with valid data', () => { + const fileName = 'valid.ome.tif' + const relativePath = `/bids-validator/validators/microscopy/__tests__/data/${fileName}` + const files = [ + { + name: fileName, + relativePath: relativePath, + path: path.join(dataDir, fileName), + }, + ] + const jsonContentDict = {} + jsonContentDict[relativePath.replace('.ome.tif', '.json')] = jsonContent + + expect.assertions(1) + return validate(files, jsonContentDict).then(issues => { + expect(issues.length).toBe(0) + }) + }) +}) diff --git a/bids-validator/validators/microscopy/checkJSONAndField.js b/bids-validator/validators/microscopy/checkJSONAndField.js index be338a256..266f3481e 100644 --- a/bids-validator/validators/microscopy/checkJSONAndField.js +++ b/bids-validator/validators/microscopy/checkJSONAndField.js @@ -9,7 +9,6 @@ const checkJSONAndField = (files, jsonContentsDict) => { .replace('.tif', '') .replace('.btf', '') .replace('.ome', '.json') - issues = issues.concat( ifJsonExist(file, possibleJsonPath, jsonContentsDict), ) @@ -40,8 +39,15 @@ const checkJSONAndField = (files, jsonContentsDict) => { const ifJsonExist = (file, possibleJsonPath, jsonContentsDict) => { let potentialSidecars = utils.files.potentialLocations(possibleJsonPath) + const chunkRegex = new RegExp('_chunk-[0-9]+') + + const jsonChunkFiles = potentialSidecars.filter( + name => jsonContentsDict.hasOwnProperty(name) && chunkRegex.exec(name), + ) + const chunkPresent = + jsonChunkFiles.length || chunkRegex.exec(file.relativePath) - const mergedDictionary = utils.files.generateMergedSidecarDictWithPath( + const mergedDictionary = utils.files.generateMergedSidecarDict( potentialSidecars, jsonContentsDict, ) @@ -54,29 +60,24 @@ const ifJsonExist = (file, possibleJsonPath, jsonContentsDict) => { code: 225, }), ] - } else { + } + + if (chunkPresent) { return checkMatrixField(file, mergedDictionary) } + + return [] } const checkMatrixField = (file, mergedDictionary) => { let issues = [] - let regex = new RegExp('_chunk-[0-9]+') - let jsonPath = mergedDictionary.sidecarName - - // ChunkTransformationMatrix is RECOMMENDED if is used in filenames - if (regex.exec(file.relativePath) || regex.exec(jsonPath)) { - if (!mergedDictionary.hasOwnProperty('ChunkTransformationMatrix')) { - issues.push( - new Issue({ - file: { - path: jsonPath, - relativePath: jsonPath, - }, - code: 223, - }), - ) - } + if (!mergedDictionary.hasOwnProperty('ChunkTransformationMatrix')) { + issues.push( + new Issue({ + file: file, + code: 223, + }), + ) } return issues } diff --git a/bids-validator/validators/microscopy/validate.js b/bids-validator/validators/microscopy/validate.js index 650ed0996..c4d90e97e 100644 --- a/bids-validator/validators/microscopy/validate.js +++ b/bids-validator/validators/microscopy/validate.js @@ -55,6 +55,15 @@ const validate = (files, jsonContentsDict) => { }), ) resolve() + } else { + issues.push( + new Issue({ + code: 227, + file: file, + evidence: `3rd byte of file does not identify file as tiff.`, + }), + ) + resolve() } }) }), diff --git a/bids-validator/validators/tsv/tsv.js b/bids-validator/validators/tsv/tsv.js index f4f81625f..bca199b15 100644 --- a/bids-validator/validators/tsv/tsv.js +++ b/bids-validator/validators/tsv/tsv.js @@ -222,8 +222,9 @@ const TSV = (file, contents, fileList, callback) => { new Issue({ file: file, evidence: headersEvidence(headers), - reason: 'Participant_id column should be named ' + - 'as sub-.', + reason: + 'Participant_id column should be named ' + + 'as sub-.', line: l, code: 212, }), @@ -243,16 +244,17 @@ const TSV = (file, contents, fileList, callback) => { // samples.tsv let samples = null if (file.name === 'samples.tsv') { + const sampleIssues = [] const sampleIdColumnValues = [] const participantIdColumnValues = [] const sampleIdColumn = headers.indexOf('sample_id') const participantIdColumn = headers.indexOf('participant_id') const sampleTypeColumn = headers.indexOf('sample_type') - // if the sample_id column is missing, an error + // if the sample_id column is missing, an error // will be raised if (sampleIdColumn === -1) { - issues.push( + sampleIssues.push( new Issue({ file: file, evidence: headersEvidence(headers), @@ -261,10 +263,10 @@ const TSV = (file, contents, fileList, callback) => { }), ) } - // if the participant_id column is missing, an error + // if the participant_id column is missing, an error // will be raised - else if (participantIdColumn === -1) { - issues.push( + if (participantIdColumn === -1) { + sampleIssues.push( new Issue({ file: file, evidence: headersEvidence(headers), @@ -273,10 +275,10 @@ const TSV = (file, contents, fileList, callback) => { }), ) } - // if the sample_type column is missing, an error + // if the sample_type column is missing, an error // will be raised - else if (sampleTypeColumn === -1) { - issues.push( + if (sampleTypeColumn === -1) { + sampleIssues.push( new Issue({ file: file, evidence: headersEvidence(headers), @@ -284,8 +286,12 @@ const TSV = (file, contents, fileList, callback) => { code: 218, }), ) - } else { - // otherwise, the samples should comprise of + } + // Fold sampleIssues into main issue array, only needed it for this + // conditional. + issues.push(...sampleIssues) + if (sampleIssues.length === 0) { + // otherwise, the samples should comprise of // sample- and one sample per row samples = [] for (let l = 1; l < rows.length; l++) { @@ -302,15 +308,15 @@ const TSV = (file, contents, fileList, callback) => { new Issue({ file: file, evidence: row[sampleIdColumn], - reason: 'sample_id column should be named ' + - 'as sample-.', + reason: + 'sample_id column should be named ' + 'as sample-.', line: l, code: 215, }), ) } } - // The participants should comprise of + // The participants should comprise of // sub- and one subject per row participants = [] for (let l = 1; l < rows.length; l++) { @@ -327,8 +333,9 @@ const TSV = (file, contents, fileList, callback) => { new Issue({ file: file, evidence: row[participantIdColumn], - reason: 'Participant_id column should be named ' + - 'as sub-.', + reason: + 'Participant_id column should be named ' + + 'as sub-.', line: l, code: 212, }), @@ -366,30 +373,32 @@ const TSV = (file, contents, fileList, callback) => { } } - // check if any incorrect patterns in sample_type column - const validSampleTypes = [ - 'cell line', - 'in vitro differentiated cells', - 'primary cell', - 'cell-free sample', - 'cloning host', - 'tissue', - 'whole organisms', - 'organoid', - 'technical sample', - ] - for (let c = 1; c < rows.length; c++) { - const row = rows[c] - if (!validSampleTypes.includes(row[sampleTypeColumn])) { - issues.push( - new Issue({ - file: file, - evidence: row[sampleTypeColumn], - reason: "sample_type can't be any value.", - line: c + 1, - code: 219, - }), - ) + if (sampleTypeColumn !== -1) { + // check if any incorrect patterns in sample_type column + const validSampleTypes = [ + 'cell line', + 'in vitro differentiated cells', + 'primary cell', + 'cell-free sample', + 'cloning host', + 'tissue', + 'whole organisms', + 'organoid', + 'technical sample', + ] + for (let c = 1; c < rows.length; c++) { + const row = rows[c] + if (!validSampleTypes.includes(row[sampleTypeColumn])) { + issues.push( + new Issue({ + file: file, + evidence: row[sampleTypeColumn], + reason: "sample_type can't be any value.", + line: c + 1, + code: 219, + }), + ) + } } } } @@ -452,10 +461,7 @@ const TSV = (file, contents, fileList, callback) => { } // blood.tsv - if ( - file.relativePath.includes('/pet/') && - file.name.endsWith('_blood.tsv') - ) { + if (file.relativePath.includes('/pet/') && file.name.endsWith('_blood.tsv')) { // Validate fields here checkheader('time', 0, file, 126) } @@ -519,7 +525,7 @@ const TSV = (file, contents, fileList, callback) => { pathList.push(fDir) } else if (fPath.includes('_ieeg.mefd/')) { // MEF3 data - const fDir = fPath.substring(0, fPath.indexOf('_ieeg.mefd/') + 10); + const fDir = fPath.substring(0, fPath.indexOf('_ieeg.mefd/') + 10) if (!pathList.includes(fDir)) { pathList.push(fDir) } diff --git a/package-lock.json b/package-lock.json index a216a8a23..6b0d14546 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,6 @@ "bids-validator", "bids-validator-web" ], - "dependencies": { - "exifreader": "^4.1.0", - "xml2js": "^0.4.23" - }, "devDependencies": { "@babel/core": "^7.7.2", "@babel/preset-env": "^7.7.1", @@ -23,7 +19,7 @@ } }, "bids-validator": { - "version": "1.8.9-dev.0", + "version": "1.8.10-dev.0", "license": "MIT", "dependencies": { "@aws-sdk/client-s3": "^3.9.0", @@ -33,6 +29,7 @@ "cross-fetch": "^3.0.6", "date-fns": "^2.7.0", "events": "^3.3.0", + "exifreader": "^4.1.0", "hed-validator": "^3.5.0", "ignore": "^4.0.2", "is-utf8": "^0.2.1", @@ -47,6 +44,7 @@ "semver": "^7.3.2", "stream-browserify": "^3.0.0", "table": "^5.2.3", + "xml2js": "^0.4.23", "yaml": "^1.10.2", "yargs": "^16.2.0" }, @@ -74,9 +72,10 @@ } }, "bids-validator-web": { - "version": "1.8.9-dev.0", + "version": "1.8.10-dev.0", "license": "MIT", "dependencies": { + "@babel/runtime": "^7.16.7", "bootstrap": "^4.3.0", "bowser": "^1.0.0", "next": "^11.1.2", @@ -88,6 +87,17 @@ "sass": "^1.32.8" } }, + "bids-validator-web/node_modules/@babel/runtime": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz", + "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, "bids-validator/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -27795,6 +27805,7 @@ "eslint-config-prettier": "^2.9.0", "eslint-plugin-prettier": "^2.6.2", "events": "^3.3.0", + "exifreader": "^4.1.0", "hed-validator": "^3.5.0", "husky": "^1.0.0-rc.13", "ignore": "^4.0.2", @@ -27814,6 +27825,7 @@ "stream-browserify": "^3.0.0", "sync-request": "6.0.0", "table": "^5.2.3", + "xml2js": "^0.4.23", "yaml": "^1.10.2", "yargs": "^16.2.0" }, @@ -27911,6 +27923,7 @@ "bids-validator-web": { "version": "file:bids-validator-web", "requires": { + "@babel/runtime": "^7.16.7", "bootstrap": "^4.3.0", "bowser": "^1.0.0", "next": "^11.1.2", @@ -27920,6 +27933,16 @@ "react-bootstrap": "^1.0.0-beta.5", "react-dom": "^17.0.2", "sass": "^1.32.8" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz", + "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + } } }, "big.js": { diff --git a/package.json b/package.json index b1a9ec06f..f4932c61f 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,5 @@ "jest-environment-node": "^24.9.0", "lerna": "^4.0.0" }, - "name": "bids-validator-monorepo", - "dependencies": { - "exifreader": "^4.1.0", - "xml2js": "^0.4.23" - } + "name": "bids-validator-monorepo" }