From 15a821e895fe65b36432f8d36be319b8c2a0be9f Mon Sep 17 00:00:00 2001 From: LitoMore Date: Tue, 1 Oct 2024 04:34:00 +0800 Subject: Add SPDX license check to ourlint (#11879) --- .jsonschema.json | 530 +----------------------------------------------- package.json | 1 + scripts/lint/ourlint.js | 45 +++- 3 files changed, 44 insertions(+), 532 deletions(-) diff --git a/.jsonschema.json b/.jsonschema.json index 46b010e5..67b001a0 100644 --- a/.jsonschema.json +++ b/.jsonschema.json @@ -61,535 +61,7 @@ "properties": { "type": { "description": "An SPDX License Identifier", - "type": "string", - "enum": [ - "0BSD", - "AAL", - "Abstyles", - "AdaCore-doc", - "Adobe-2006", - "Adobe-Glyph", - "ADSL", - "AFL-1.1", - "AFL-1.2", - "AFL-2.0", - "AFL-2.1", - "AFL-3.0", - "Afmparse", - "AGPL-1.0-only", - "AGPL-1.0-or-later", - "AGPL-3.0-only", - "AGPL-3.0-or-later", - "Aladdin", - "AMDPLPA", - "AML", - "AMPAS", - "ANTLR-PD", - "ANTLR-PD-fallback", - "Apache-1.0", - "Apache-1.1", - "Apache-2.0", - "APAFML", - "APL-1.0", - "App-s2p", - "APSL-1.0", - "APSL-1.1", - "APSL-1.2", - "APSL-2.0", - "Arphic-1999", - "Artistic-1.0", - "Artistic-1.0-cl8", - "Artistic-1.0-Perl", - "Artistic-2.0", - "ASWF-Digital-Assets-1.0", - "ASWF-Digital-Assets-1.1", - "Baekmuk", - "Bahyph", - "Barr", - "Beerware", - "Bitstream-Charter", - "Bitstream-Vera", - "BitTorrent-1.0", - "BitTorrent-1.1", - "blessing", - "BlueOak-1.0.0", - "Boehm-GC", - "Borceux", - "Brian-Gladman-3-Clause", - "BSD-1-Clause", - "BSD-2-Clause", - "BSD-2-Clause-Patent", - "BSD-2-Clause-Views", - "BSD-3-Clause", - "BSD-3-Clause-Attribution", - "BSD-3-Clause-Clear", - "BSD-3-Clause-LBNL", - "BSD-3-Clause-Modification", - "BSD-3-Clause-No-Military-License", - "BSD-3-Clause-No-Nuclear-License", - "BSD-3-Clause-No-Nuclear-License-2014", - "BSD-3-Clause-No-Nuclear-Warranty", - "BSD-3-Clause-Open-MPI", - "BSD-4-Clause", - "BSD-4-Clause-Shortened", - "BSD-4-Clause-UC", - "BSD-4.3RENO", - "BSD-4.3TAHOE", - "BSD-Advertising-Acknowledgement", - "BSD-Attribution-HPND-disclaimer", - "BSD-Protection", - "BSD-Source-Code", - "BSL-1.0", - "BUSL-1.1", - "bzip2-1.0.6", - "C-UDA-1.0", - "CAL-1.0", - "CAL-1.0-Combined-Work-Exception", - "Caldera", - "CATOSL-1.1", - "CC-BY-1.0", - "CC-BY-2.0", - "CC-BY-2.5", - "CC-BY-2.5-AU", - "CC-BY-3.0", - "CC-BY-3.0-AT", - "CC-BY-3.0-DE", - "CC-BY-3.0-IGO", - "CC-BY-3.0-NL", - "CC-BY-3.0-US", - "CC-BY-4.0", - "CC-BY-NC-1.0", - "CC-BY-NC-2.0", - "CC-BY-NC-2.5", - "CC-BY-NC-3.0", - "CC-BY-NC-3.0-DE", - "CC-BY-NC-4.0", - "CC-BY-NC-ND-1.0", - "CC-BY-NC-ND-2.0", - "CC-BY-NC-ND-2.5", - "CC-BY-NC-ND-3.0", - "CC-BY-NC-ND-3.0-DE", - "CC-BY-NC-ND-3.0-IGO", - "CC-BY-NC-ND-4.0", - "CC-BY-NC-SA-1.0", - "CC-BY-NC-SA-2.0", - "CC-BY-NC-SA-2.0-DE", - "CC-BY-NC-SA-2.0-FR", - "CC-BY-NC-SA-2.0-UK", - "CC-BY-NC-SA-2.5", - "CC-BY-NC-SA-3.0", - "CC-BY-NC-SA-3.0-DE", - "CC-BY-NC-SA-3.0-IGO", - "CC-BY-NC-SA-4.0", - "CC-BY-ND-1.0", - "CC-BY-ND-2.0", - "CC-BY-ND-2.5", - "CC-BY-ND-3.0", - "CC-BY-ND-3.0-DE", - "CC-BY-ND-4.0", - "CC-BY-SA-1.0", - "CC-BY-SA-2.0", - "CC-BY-SA-2.0-UK", - "CC-BY-SA-2.1-JP", - "CC-BY-SA-2.5", - "CC-BY-SA-3.0", - "CC-BY-SA-3.0-AT", - "CC-BY-SA-3.0-DE", - "CC-BY-SA-3.0-IGO", - "CC-BY-SA-4.0", - "CC-PDDC", - "CC0-1.0", - "CDDL-1.0", - "CDDL-1.1", - "CDL-1.0", - "CDLA-Permissive-1.0", - "CDLA-Permissive-2.0", - "CDLA-Sharing-1.0", - "CECILL-1.0", - "CECILL-1.1", - "CECILL-2.0", - "CECILL-2.1", - "CECILL-B", - "CECILL-C", - "CERN-OHL-1.1", - "CERN-OHL-1.2", - "CERN-OHL-P-2.0", - "CERN-OHL-S-2.0", - "CERN-OHL-W-2.0", - "CFITSIO", - "checkmk", - "ClArtistic", - "Clips", - "CMU-Mach", - "CNRI-Jython", - "CNRI-Python", - "CNRI-Python-GPL-Compatible", - "COIL-1.0", - "Community-Spec-1.0", - "Condor-1.1", - "copyleft-next-0.3.0", - "copyleft-next-0.3.1", - "Cornell-Lossless-JPEG", - "CPAL-1.0", - "CPL-1.0", - "CPOL-1.02", - "Crossword", - "CrystalStacker", - "CUA-OPL-1.0", - "Cube", - "curl", - "D-FSL-1.0", - "diffmark", - "DL-DE-BY-2.0", - "DOC", - "Dotseqn", - "DRL-1.0", - "DSDP", - "dtoa", - "dvipdfm", - "ECL-1.0", - "ECL-2.0", - "EFL-1.0", - "EFL-2.0", - "eGenix", - "Elastic-2.0", - "Entessa", - "EPICS", - "EPL-1.0", - "EPL-2.0", - "ErlPL-1.1", - "etalab-2.0", - "EUDatagrid", - "EUPL-1.0", - "EUPL-1.1", - "EUPL-1.2", - "Eurosym", - "Fair", - "FDK-AAC", - "Frameworx-1.0", - "FreeBSD-DOC", - "FreeImage", - "FSFAP", - "FSFUL", - "FSFULLR", - "FSFULLRWD", - "FTL", - "GD", - "GFDL-1.1-invariants-only", - "GFDL-1.1-invariants-or-later", - "GFDL-1.1-no-invariants-only", - "GFDL-1.1-no-invariants-or-later", - "GFDL-1.1-only", - "GFDL-1.1-or-later", - "GFDL-1.2-invariants-only", - "GFDL-1.2-invariants-or-later", - "GFDL-1.2-no-invariants-only", - "GFDL-1.2-no-invariants-or-later", - "GFDL-1.2-only", - "GFDL-1.2-or-later", - "GFDL-1.3-invariants-only", - "GFDL-1.3-invariants-or-later", - "GFDL-1.3-no-invariants-only", - "GFDL-1.3-no-invariants-or-later", - "GFDL-1.3-only", - "GFDL-1.3-or-later", - "Giftware", - "GL2PS", - "Glide", - "Glulxe", - "GLWTPL", - "gnuplot", - "GPL-1.0-only", - "GPL-1.0-or-later", - "GPL-2.0-only", - "GPL-2.0-or-later", - "GPL-3.0-only", - "GPL-3.0-or-later", - "Graphics-Gems", - "gSOAP-1.3b", - "HaskellReport", - "Hippocratic-2.1", - "HP-1986", - "HPND", - "HPND-export-US", - "HPND-Markus-Kuhn", - "HPND-sell-variant", - "HPND-sell-variant-MIT-disclaimer", - "HTMLTIDY", - "IBM-pibs", - "ICU", - "IEC-Code-Components-EULA", - "IJG", - "IJG-short", - "ImageMagick", - "iMatix", - "Imlib2", - "Info-ZIP", - "Inner-Net-2.0", - "Intel", - "Intel-ACPI", - "Interbase-1.0", - "IPA", - "IPL-1.0", - "ISC", - "Jam", - "JasPer-2.0", - "JPL-image", - "JPNIC", - "JSON", - "Kazlib", - "Knuth-CTAN", - "LAL-1.2", - "LAL-1.3", - "Latex2e", - "Latex2e-translated-notice", - "Leptonica", - "LGPL-2.0-only", - "LGPL-2.0-or-later", - "LGPL-2.1-only", - "LGPL-2.1-or-later", - "LGPL-3.0-only", - "LGPL-3.0-or-later", - "LGPLLR", - "Libpng", - "libpng-2.0", - "libselinux-1.0", - "libtiff", - "libutil-David-Nugent", - "LiLiQ-P-1.1", - "LiLiQ-R-1.1", - "LiLiQ-Rplus-1.1", - "Linux-man-pages-1-para", - "Linux-man-pages-copyleft", - "Linux-man-pages-copyleft-2-para", - "Linux-man-pages-copyleft-var", - "Linux-OpenIB", - "LOOP", - "LPL-1.0", - "LPL-1.02", - "LPPL-1.0", - "LPPL-1.1", - "LPPL-1.2", - "LPPL-1.3a", - "LPPL-1.3c", - "LZMA-SDK-9.11-to-9.20", - "LZMA-SDK-9.22", - "MakeIndex", - "Martin-Birgmeier", - "metamail", - "Minpack", - "MirOS", - "MIT", - "MIT-0", - "MIT-advertising", - "MIT-CMU", - "MIT-enna", - "MIT-feh", - "MIT-Festival", - "MIT-Modern-Variant", - "MIT-open-group", - "MIT-Wu", - "MITNFA", - "Motosoto", - "mpi-permissive", - "mpich2", - "MPL-1.0", - "MPL-1.1", - "MPL-2.0", - "MPL-2.0-no-copyleft-exception", - "mplus", - "MS-LPL", - "MS-PL", - "MS-RL", - "MTLL", - "MulanPSL-1.0", - "MulanPSL-2.0", - "Multics", - "Mup", - "NAIST-2003", - "NASA-1.3", - "Naumen", - "NBPL-1.0", - "NCGL-UK-2.0", - "NCSA", - "Net-SNMP", - "NetCDF", - "Newsletr", - "NGPL", - "NICTA-1.0", - "NIST-PD", - "NIST-PD-fallback", - "NIST-Software", - "NLOD-1.0", - "NLOD-2.0", - "NLPL", - "Nokia", - "NOSL", - "Noweb", - "NPL-1.0", - "NPL-1.1", - "NPOSL-3.0", - "NRL", - "NTP", - "NTP-0", - "O-UDA-1.0", - "OCCT-PL", - "OCLC-2.0", - "ODbL-1.0", - "ODC-By-1.0", - "OFFIS", - "OFL-1.0", - "OFL-1.0-no-RFN", - "OFL-1.0-RFN", - "OFL-1.1", - "OFL-1.1-no-RFN", - "OFL-1.1-RFN", - "OGC-1.0", - "OGDL-Taiwan-1.0", - "OGL-Canada-2.0", - "OGL-UK-1.0", - "OGL-UK-2.0", - "OGL-UK-3.0", - "OGTSL", - "OLDAP-1.1", - "OLDAP-1.2", - "OLDAP-1.3", - "OLDAP-1.4", - "OLDAP-2.0", - "OLDAP-2.0.1", - "OLDAP-2.1", - "OLDAP-2.2", - "OLDAP-2.2.1", - "OLDAP-2.2.2", - "OLDAP-2.3", - "OLDAP-2.4", - "OLDAP-2.5", - "OLDAP-2.6", - "OLDAP-2.7", - "OLDAP-2.8", - "OLFL-1.3", - "OML", - "OpenPBS-2.3", - "OpenSSL", - "OPL-1.0", - "OPL-UK-3.0", - "OPUBL-1.0", - "OSET-PL-2.1", - "OSL-1.0", - "OSL-1.1", - "OSL-2.0", - "OSL-2.1", - "OSL-3.0", - "Parity-6.0.0", - "Parity-7.0.0", - "PDDL-1.0", - "PHP-3.0", - "PHP-3.01", - "Plexus", - "PolyForm-Noncommercial-1.0.0", - "PolyForm-Small-Business-1.0.0", - "PostgreSQL", - "PSF-2.0", - "psfrag", - "psutils", - "Python-2.0", - "Python-2.0.1", - "Qhull", - "QPL-1.0", - "QPL-1.0-INRIA-2004", - "Rdisc", - "RHeCos-1.1", - "RPL-1.1", - "RPL-1.5", - "RPSL-1.0", - "RSA-MD", - "RSCPL", - "Ruby", - "SAX-PD", - "Saxpath", - "SCEA", - "SchemeReport", - "Sendmail", - "Sendmail-8.23", - "SGI-B-1.0", - "SGI-B-1.1", - "SGI-B-2.0", - "SGP4", - "SHL-0.5", - "SHL-0.51", - "SimPL-2.0", - "SISSL", - "SISSL-1.2", - "Sleepycat", - "SMLNJ", - "SMPPL", - "SNIA", - "snprintf", - "Spencer-86", - "Spencer-94", - "Spencer-99", - "SPL-1.0", - "SSH-OpenSSH", - "SSH-short", - "SSPL-1.0", - "SugarCRM-1.1.3", - "SunPro", - "SWL", - "Symlinks", - "TAPR-OHL-1.0", - "TCL", - "TCP-wrappers", - "TermReadKey", - "TMate", - "TORQUE-1.1", - "TOSL", - "TPDL", - "TPL-1.0", - "TTWL", - "TU-Berlin-1.0", - "TU-Berlin-2.0", - "UCAR", - "UCL-1.0", - "Unicode-DFS-2015", - "Unicode-DFS-2016", - "Unicode-TOU", - "UnixCrypt", - "Unlicense", - "UPL-1.0", - "Vim", - "VOSTROM", - "VSL-1.0", - "W3C", - "W3C-19980720", - "W3C-20150513", - "w3m", - "Watcom-1.0", - "Widget-Workshop", - "Wsuipa", - "WTFPL", - "X11", - "X11-distribute-modifications-variant", - "Xdebug-1.03", - "Xerox", - "Xfig", - "XFree86-1.1", - "xinetd", - "xlock", - "Xnet", - "xpp", - "XSkat", - "YPL-1.0", - "YPL-1.1", - "Zed", - "Zend-2.0", - "Zimbra-1.3", - "Zimbra-1.4", - "Zlib", - "zlib-acknowledgement", - "ZPL-1.1", - "ZPL-2.0", - "ZPL-2.1" - ] + "type": "string" } }, "additionalProperties": false diff --git a/package.json b/package.json index 5dbb1a2e..c7948e7f 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "markdown-link-check": "3.12.1", "mocha": "10.4.0", "named-html-entities-json": "1.0.0", + "spdx-license-ids": "3.0.20", "svg-path-bbox": "2.0.0", "svg-path-segments": "2.0.1", "svglint": "2.7.1", diff --git a/scripts/lint/ourlint.js b/scripts/lint/ourlint.js index b7561716..43aec487 100644 --- a/scripts/lint/ourlint.js +++ b/scripts/lint/ourlint.js @@ -10,14 +10,21 @@ * @typedef {IconData[]} IconsData */ +import fs from 'node:fs/promises'; import path from 'node:path'; import process from 'node:process'; import fakeDiff from 'fake-diff'; -import {collator, getIconsDataString, normalizeNewlines} from '../../sdk.mjs'; +import { + collator, + getDirnameFromImportMeta, + getIconsDataString, + normalizeNewlines, + titleToSlug, +} from '../../sdk.mjs'; /** * Contains our tests so they can be isolated from each other. - * @type {{[k: string]: (arg0: {icons: IconsData}, arg1: string) => string | undefined}} + * @type {{[k: string]: (arg0: {icons: IconsData}, arg1: string) => Promise | string | undefined}} */ const TESTS = { /** @@ -176,7 +183,6 @@ const TESTS = { } if (isRawGithubAssetUrl($url)) { - // https://github.com/LitoMore/simple-icons-cdn/blob/main/media/imgcat-screenshot.webp const [, owner, repo, hash, ...directory] = $url.pathname.split('/'); const expectedUrl = `https://github.com/${owner}/${repo}/blob/${hash}/${directory.join('/')}`; invalidUrls.push(fakeDiff(url, expectedUrl)); @@ -199,6 +205,39 @@ const TESTS = { return `Invalid URLs:\n\n${invalidUrls.join('\n\n')}`; } }, + + /* Check if all licenses are valid SPDX identifiers */ + async checkLicense(data) { + const spdxLicenseIds = new Set( + JSON.parse( + await fs.readFile( + path.join( + getDirnameFromImportMeta(import.meta.url), + '..', + '..', + 'node_modules/spdx-license-ids/index.json', + ), + 'utf8', + ), + ), + ); + const badLicenses = []; + for (const {title, slug, license} of data.icons) { + if ( + license && + license.type !== 'custom' && + !spdxLicenseIds.has(license.type) + ) { + badLicenses.push( + `${title} (${slug ?? titleToSlug(title)}) has not a valid SPDX license.`, + ); + } + } + + if (badLicenses.length > 0) { + return `Bad licenses:\n\n${badLicenses.join('\n')}\n\nSee the valid license indentifiers at https://spdx.org/licenses`; + } + }, }; const iconsDataString = await getIconsDataString(); -- cgit v1.2.3-70-g09d2