mirror of
				https://github.com/Mibew/simple-icons.git
				synced 2025-10-31 02:25:59 +03:00 
			
		
		
		
	Add icon license to JSON linting (and change JSON linting dependency) (#4945)
* Add "license" object to the data file JSON schema * Add license to GNU and GNU social As an example, based on the discussion in: https://github.com/simple-icons/simple-icons/issues/1167 * Use `"additionalProperties": false` in JSON schema ... to detect properties in the data file that shouldn't be there. For more info, see: https://json-schema.org/understanding-json-schema/reference/object.html * Update JSON scheme descriptions * Switch from jsonlint2 to jsonschema This gives is better support for advanced features of JSON schema. A couple of clarifications: - There does exist a jsonschema-cli package, but it is rather limited and crucially doens't exit with a non-zero exit code if there is an error. (it is also pretty old and not maintained), hence the custom script. - I renamed .jsonlintschema 1) for clarity (lint is no longer accurate) and 2) the .json extension allows easy imorting in the script and 3) it adds syntax highlighting. - The script outputs the number of errors in the end because the output gets pretty big pretty quickly, this way you can see it easily from your CLI. - We could customize how the errors are logged, but I feel that is beyond this PR. * Two minor changes * Use `oneOf` to require URL for custom licenses The updated configuration allows the `"license"` field to be either 1) a SPDX license, optional with a URL 2) a "custom" license with a required URL Read more about the "oneOf" feature of jsonschema at: https://json-schema.org/understanding-json-schema/reference/combining.html#oneof * Include license field in Contributing Guidelines
This commit is contained in:
		
							parent
							
								
									9c029bc706
								
							
						
					
					
						commit
						39269e7d39
					
				| @ -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 | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										162
									
								
								.jsonschema.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								.jsonschema.json
									
									
									
									
									
										Normal file
									
								
							| @ -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" } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -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" | ||||
|     } | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
							
								
								
									
										67
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										67
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -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", | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
							
								
								
									
										19
									
								
								scripts/jsonlint.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								scripts/jsonlint.js
									
									
									
									
									
										Normal file
									
								
							| @ -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); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user