From 6926d6a99acdeecfd7e494d6884b92cddb226b79 Mon Sep 17 00:00:00 2001 From: Antoine Motet Date: Thu, 15 Jun 2017 21:45:04 +0200 Subject: [PATCH] Add `relaxed` option to allow invalid licenses and exception names Fix #11. --- index.js | 4 ++-- parse.js | 20 ++++++++++++++++---- scan.js | 20 +++----------------- test/index.js | 24 ++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/index.js b/index.js index 52fab56..040e26a 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,6 @@ var scan = require('./scan') var parse = require('./parse') -module.exports = function (source) { - return parse(scan(source)) +module.exports = function (source, options) { + return parse(scan(source), options) } diff --git a/parse.js b/parse.js index a4a52ce..a9a7b1a 100644 --- a/parse.js +++ b/parse.js @@ -1,11 +1,17 @@ 'use strict' +var licenses = require('spdx-license-ids') +var exceptions = require('spdx-exceptions') + // The ABNF grammar in the spec is totally ambiguous. // // This parser follows the operator precedence defined in the // `Order of Precedence and Parentheses` section. - -module.exports = function (tokens) { +// +// options: +// - Set `relaxed` to `true` to accept invalid license or exception IDs. +module.exports = function (tokens, options) { + options = options || {} var index = 0 function hasMore () { @@ -34,7 +40,10 @@ module.exports = function (tokens) { function parseWith () { if (parseOperator('WITH')) { var t = token() - if (t && t.type === 'EXCEPTION') { + if (t && t.type === 'IDENTIFIER') { + if (!options.relaxed && exceptions.indexOf(t.string) === -1) { + throw new Error('`' + t.string + '` is not a valid exception name') + } next() return t.string } @@ -67,7 +76,10 @@ module.exports = function (tokens) { function parseLicense () { var t = token() - if (t && t.type === 'LICENSE') { + if (t && t.type === 'IDENTIFIER') { + if (!options.relaxed && licenses.indexOf(t.string) === -1) { + throw new Error('`' + t.string + '` is not a valid license name') + } next() var node = {license: t.string} if (parseOperator('+')) { diff --git a/scan.js b/scan.js index c867c07..a146d19 100644 --- a/scan.js +++ b/scan.js @@ -1,8 +1,5 @@ 'use strict' -var licenses = require('spdx-license-ids') -var exceptions = require('spdx-exceptions') - module.exports = function (source) { var index = 0 @@ -80,22 +77,11 @@ module.exports = function (source) { } function identifier () { - var begin = index var string = idstring() - - if (licenses.indexOf(string) !== -1) { - return { - type: 'LICENSE', - string: string - } - } else if (exceptions.indexOf(string) !== -1) { - return { - type: 'EXCEPTION', - string: string - } + return string && { + type: 'IDENTIFIER', + string: string } - - index = begin } // Tries to read the next token. Returns `undefined` if no token is diff --git a/test/index.js b/test/index.js index 46318fa..a5ece86 100644 --- a/test/index.js +++ b/test/index.js @@ -83,3 +83,27 @@ it('parses `AND`, `OR` and `WITH` with the correct precedence', function () { } ) }) + +it('rejects invalid license and exception names by default', function () { + assert.throws( + function () { p('unknownLicense') }, + /`unknownLicense` is not a valid license name/ + ) + + assert.throws( + function () { p('MIT WITH unknownException') }, + /`unknownException` is not a valid exception name/ + ) +}) + +it('accepts invalid license and exception names in relaxed mode', function () { + assert.deepEqual( + p('unknownLicense', {relaxed: true}), + {license: 'unknownLicense'} + ) + + assert.deepEqual( + p('MIT WITH unknownException', {relaxed: true}), + {license: 'MIT', exception: 'unknownException'} + ) +})