diff --git a/package-lock.json b/package-lock.json index dee5f96..74f81a3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,9 +23,9 @@ "esbuild": "^0.28.1", "jsdom": "^30.0.1", "minimist": "^1.2.8", - "oss-license-name-to-url": "^1.2.1", "postcss": "^8.5.25", "sass-embedded": "^1.100.0", + "spdx-license-list": "^6.12.0", "typescript": "^7.0.2" }, "engines": { @@ -2274,25 +2274,6 @@ "node": ">=0.10.0" } }, - "node_modules/osi-licenses": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/osi-licenses/-/osi-licenses-0.1.1.tgz", - "integrity": "sha512-ZGAGO6dIxTS/mXxEJCpIdYetAoxIOOr7uYpMOoDWo4+b/6rf+2GagOjTbegL+eoMI8aYAiyNgKWUT7vWJRPl9A==", - "dev": true, - "engines": { - "node": ">=0.10", - "npm": ">=1.2" - } - }, - "node_modules/oss-license-name-to-url": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/oss-license-name-to-url/-/oss-license-name-to-url-1.2.1.tgz", - "integrity": "sha512-apFbKq0EAYi70q0pOpS0tDfSviZYdG3KM6U1GpofZPsRMwgDga0DQiPQ/GHyQx7PDDrLCGvFBNPLMLV/K4Jr4Q==", - "dev": true, - "dependencies": { - "osi-licenses": "^0.1.0" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -3383,6 +3364,19 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-license-list": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/spdx-license-list/-/spdx-license-list-6.12.0.tgz", + "integrity": "sha512-+nUYqm3aZMSHbjsthK+i/HHI2okTElCvqwUd4k8QcSk+FTGgjq+fsdFj2wZOaX6XmR2JdWhf/NeflNnvKOjcnQ==", + "dev": true, + "license": "CC0-1.0", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/stylehacks": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.11.tgz", diff --git a/package.json b/package.json index 51425a4..50603b1 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,9 @@ "esbuild": "^0.28.1", "jsdom": "^30.0.1", "minimist": "^1.2.8", - "oss-license-name-to-url": "^1.2.1", "postcss": "^8.5.25", "sass-embedded": "^1.100.0", + "spdx-license-list": "^6.12.0", "typescript": "^7.0.2" }, "repository": { diff --git a/tools/lib/license-header.mjs b/tools/lib/license-header.mjs index 44a38df..fd281ac 100644 --- a/tools/lib/license-header.mjs +++ b/tools/lib/license-header.mjs @@ -3,28 +3,45 @@ import path from 'node:path'; import {createRequire} from 'node:module'; const require = createRequire(import.meta.url); -const nameToUrl = require('oss-license-name-to-url'); +const spdxLicenseList = require('spdx-license-list'); /* バンドルに含まれた依存ライブラリのライセンス一覧をヘッダとして出力する。 - licensify(browserifyプラグイン)のextract / createEachHeaderの仕様に合わせてあり、 - URL付与も同じ oss-license-name-to-url を使う。 + licensify(browserifyプラグイン)のextract / createEachHeaderの仕様に合わせてある。 - 収集対象だけがlicensifyと異なる: + licensifyと異なる点が2つある。 + + ひとつは収集対象: licensify … 依存グラフを歩く途中で見つけたpackage.json全部。Node互換shim(process / timers-browserify / browser-resolve)や、最終出力に残らないreact-dom開発版も含む こちら … metafileのinputsに実際に入ったファイルの所属パッケージのみ 実際に配布されるコードのライセンスを列挙する点でこちらが正確。 + + もうひとつはURLの引き方。licensifyが使うoss-license-name-to-urlは2015年で更新が + 止まっており、0BSD / MIT-0 / BlueOak-1.0.0 のようにその後SPDXへ登録された識別子を + 解決できずURLなしになる。こちらはSPDXの一覧をそのまま引く。 */ const PROPS = ['license', 'licenses', 'author', 'maintainers', 'contributors', 'homepage', 'version']; const OPERATORS = ['OR', 'AND']; +/* SPDXの識別子は大文字小文字を区別せずに照合する決まりなので、小文字で引けるようにする */ +const spdxIds = new Map(Object.keys(spdxLicenseList).map((id) => [id.toLowerCase(), id])); + const isPlainObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v); +/* + spdx-license-listが持つurlはライセンスごとに提供元がばらつく(ISCはisc.orgの一覧ページ、 + 0BSDは個人サイト)ため、識別子の確認だけに使い、URLはSPDXの公式ページへ揃える。 + */ +function licenseUrl(name) { + const id = spdxIds.get(name.toLowerCase()); + return id ? `https://spdx.org/licenses/${id}.html` : null; +} + function appendUrlToLicense(name) { if (!name) return name; - const url = nameToUrl(name); + const url = licenseUrl(name); return url ? `${name} (${url})` : name; }