diff --git a/.jsonlintschema b/.jsonlintschema deleted file mode 100644 index 5618db9a9..000000000 --- a/.jsonlintschema +++ /dev/null @@ -1,46 +0,0 @@ -{ - "title": "Simple Icons", - "type": "object", - "properties": { - "icons": { - "description": "The list of icons", - "type": "array", - "items": { - "description": "A single icon", - "type": "object", - "properties": { - "title": { - "description": "The icons name", - "type": "string", - "required": true - }, - "slug": { - "description": "The brand name slug (used as filename in icons/)", - "type": "string", - "pattern": "^[a-z0-9\\-]+_[a-z0-9\\-]+$", - "required": false - }, - "hex": { - "description": "The icons color, as HEX (without #)", - "type": "string", - "pattern": "^[0-9A-F]{6}$", - "required": true - }, - "source": { - "description": "The website from which the icon originated", - "type": "string", - "pattern": "^https?://[^\\s]+$", - "required": true - }, - "guidelines": { - "description": "The brand guidelines for the icon and/or color", - "type": "string", - "pattern": "^https?://[^\\s]+$", - "required": false - } - }, - "required": true - } - } - } -} diff --git a/.jsonschema.json b/.jsonschema.json new file mode 100644 index 000000000..0cfcc9908 --- /dev/null +++ b/.jsonschema.json @@ -0,0 +1,162 @@ +{ + "title": "Simple Icons", + "definitions": { + "brand": { + "description": "A single brand", + "type": "object", + "required": ["title", "hex", "source"], + "properties": { + "title": { + "description": "The name of the brand", + "type": "string" + }, + "slug": { + "description": "The brand name slug (used as filename in icons/)", + "type": "string", + "pattern": "^[a-z0-9\\-]+_[a-z0-9\\-]+$", + "required": false + }, + "hex": { + "description": "The brand color as a 6-character value (without #)", + "type": "string", + "pattern": "^[0-9A-F]{6}$" + }, + "source": { + "description": "The website from which the icon was sourced", + "$ref": "#/definitions/url" + }, + "guidelines": { + "description": "The brand guidelines", + "$ref": "#/definitions/url" + }, + "license": { + "description": "The license for the icon", + "oneOf": [ + { + "type": "object", + "required": ["type", "url"], + "properties": { + "type": { + "description": "The license name or 'custom'", + "type": "string", + "enum": ["custom"] + }, + "url": { + "description": "The URL to the license text by the brand", + "$ref": "#/definitions/url" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": ["type"], + "properties": { + "type": { + "description": "An SPDX License Identifier", + "type": "string", + "enum": [ + "0BSD", + "AAL", + "AFL-1.1", + "AFL-1.2", + "AFL-2.0", + "AFL-3.0", + "Afmparse", + "AGPL-1.0-only", + "AGPL-1.0-or-later", + "AGPL-3.0-only", + "AGPL-3.0-or-later", + "Aladdin", + "AML", + "AMPAS", + "Apache-1.0", + "Apache-1.1", + "Apache-2.0", + "APL-1.0", + "Artistic-1.0", + "Artistic-1.0-cl8", + "Artistic-1.0-Perl", + "Artistic-2.0", + "CC-BY-1.0", + "CC-BY-2.0", + "CC-BY-2.5", + "CC-BY-3.0", + "CC-BY-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-4.0", + "CC-BY-NC-SA-1.0", + "CC-BY-NC-SA-2.0", + "CC-BY-NC-SA-2.5", + "CC-BY-NC-SA-3.0", + "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-4.0", + "CC-BY-SA-1.0", + "CC-BY-SA-2.0", + "CC-BY-SA-2.5", + "CC-BY-SA-3.0", + "CC-BY-SA-4.0", + "CC-PDDC", + "CC0-1.0", + "CDDL-1.0", + "CDDL-1.1", + "ClArtistic", + "copyleft-next-0.3.0", + "copyleft-next-0.3.1", + "CPAL-1.0", + "CPL-1.0", + "CPOL-1.02", + "EUPL-1.0", + "EUPL-1.1", + "EUPL-1.2", + "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", + "LAL-1.2", + "LAL-1.3", + "NLPL", + "OPL-1.0", + "Unlicense", + "UPL-1.0", + "WTFPL" + ] + }, + "url": { + "description": "The URL to the license text by the brand", + "$ref": "#/definitions/url" + } + }, + "additionalProperties": false + } + ] + + } + }, + "additionalProperties": false + }, + "url": { + "$id": "#url", + "type": "string", + "pattern": "^https?://[^\\s]+$" + } + }, + + "type": "object", + "properties": { + "icons": { + "description": "A list of brands", + "type": "array", + "items": { "$ref": "#/definitions/brand" } + } + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cba023b9e..5e424f2d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -189,16 +189,23 @@ Icon metadata should be added to the `_data/simple-icons.json` file. Each icon i * A `hex` color value that matches the brand's primary color. All uppercase and without the `#` pound symbol.) * The `source` URL of the logo being used. There are [more details below](#source-guidelines). -There is also an optional field that may be used to specify the brand guidelines/presskit/etc. This is useful if the SVG file was sourced from a different place. +Additionally, there are also optional fields that may provided for an icon: -Here is the object for The Movie Database as an example: +- The `guidelines` may be used to specify the URL of the brand's guidelines/presskit/etc. This is useful if the SVG file was sourced from a different place. +- The `license` may be used to record the license under which the icon is available. This is an object with a `type` and `url`. The `type` should be an [SPDX License ID](https://spdx.org/licenses/) or `"custom"`, the `url` is optional unless the `type` is `"custom"`. + +Here is the object of a fictional brand as an example: ```json { - "title": "The Movie Database", - "hex": "01D277", - "source": "https://www.themoviedb.org/about/logos-attribution", - "guidelines": "https://www.themoviedb.org/about/logos-attribution" + "title": "A Fictional Brand", + "hex": "123456", + "source": "https://www.a-fictional-brand.org/logo", + "guidelines": "https://www.a-fictional-brand.org/brand-guidelines", + "license": { + "type": "CC0-1.0", + "url": "https://www.a-fictional-brand.org/logo/license" + } } ``` diff --git a/_data/simple-icons.json b/_data/simple-icons.json index f0545fd0b..057f8327a 100644 --- a/_data/simple-icons.json +++ b/_data/simple-icons.json @@ -2990,7 +2990,10 @@ { "title": "GNU", "hex": "A42E2B", - "source": "https://gnu.org" + "source": "https://gnu.org", + "license": { + "type": "CC-BY-SA-2.0" + } }, { "title": "GNU Bash", @@ -3015,7 +3018,10 @@ { "title": "GNU social", "hex": "A22430", - "source": "https://www.gnu.org/graphics/social.html" + "source": "https://www.gnu.org/graphics/social.html", + "license": { + "type": "CC0-1.0" + } }, { "title": "Go", diff --git a/package-lock.json b/package-lock.json index 8ba780bc1..399f18d23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -761,12 +761,6 @@ "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", "dev": true }, - "JSV": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", - "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=", - "dev": true - }, "abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -2273,12 +2267,6 @@ "function-bind": "^1.1.1" } }, - "has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3382,15 +3370,11 @@ "minimist": "^1.2.5" } }, - "jsonlint2": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/jsonlint2/-/jsonlint2-1.7.1.tgz", - "integrity": "sha512-LNhh7oMVw5ooebi1ArmKPeOUWNfUd2NBGM065KVSdfSJs/OmdTTvEvAXkW8gf1XG6gJ/qn1SRIYXwufxHnbgQw==", - "dev": true, - "requires": { - "JSV": ">= 4.0.x", - "nomnom": "1.8.1" - } + "jsonschema": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", + "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", + "dev": true }, "jsprim": { "version": "1.4.1", @@ -3926,41 +3910,6 @@ } } }, - "nomnom": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", - "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "dev": true, - "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true - }, - "chalk": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, - "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" - } - }, - "strip-ansi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true - } - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -5791,12 +5740,6 @@ "integrity": "sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q==", "dev": true }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", diff --git a/package.json b/package.json index 5e53f68a3..f8ecea5f9 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "editorconfig-checker": "3.3.0", "jest": "26.6.3", "jest-diff": "26.6.2", - "jsonlint2": "1.7.1", + "jsonschema": "1.4.0", "npm-run-all": "4.1.5", "svg-path-bbox": "0.2.0", "svglint": "1.0.7", @@ -34,7 +34,7 @@ "clean": "rm -f icons/*.js index.js", "lint": "run-s our-lint jsonlint svglint wslint", "our-lint": "node scripts/lint.js", - "jsonlint": "jsonlint _data/simple-icons.json -q -V .jsonlintschema", + "jsonlint": "node scripts/jsonlint.js", "svglint": "svglint icons/*.svg --ci", "wslint": "editorconfig-checker -exclude \\.svg$", "prepublishOnly": "npm run build", diff --git a/scripts/jsonlint.js b/scripts/jsonlint.js new file mode 100644 index 000000000..94a8b8a68 --- /dev/null +++ b/scripts/jsonlint.js @@ -0,0 +1,19 @@ +const path = require("path"); +const Validator = require("jsonschema").Validator; + +const schemaFile = path.resolve(__dirname, "..", ".jsonschema.json"); +const dataFile = path.resolve(__dirname, "..", "_data", "simple-icons.json"); + +const schema = require(schemaFile); +const data = require(dataFile); + +const validator = new Validator(); +const result = validator.validate(data, schema); +if (result.errors.length > 0) { + result.errors.forEach((error) => { + console.error(error); + }); + + console.error(`Found ${result.errors.length} error(s) in simple-icons.json`); + process.exit(1); +}