mirror of
https://github.com/simple-icons/simple-icons.git
synced 2025-01-05 01:20:39 +02:00
Refactor JSONSchema and URL checks (#10276)
This commit is contained in:
parent
3e65e780f6
commit
788014313d
@ -599,9 +599,8 @@
|
|||||||
"required": ["type", "url"],
|
"required": ["type", "url"],
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {
|
"type": {
|
||||||
"description": "The license name or 'custom'",
|
"description": "Custom license type",
|
||||||
"type": "string",
|
"const": "custom"
|
||||||
"enum": ["custom"]
|
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"description": "The URL to the license text by the brand",
|
"description": "The URL to the license text by the brand",
|
||||||
@ -617,7 +616,7 @@
|
|||||||
},
|
},
|
||||||
"duplicate": {
|
"duplicate": {
|
||||||
"$id": "#duplicate",
|
"$id": "#duplicate",
|
||||||
"description": "A \"dup\" brand",
|
"description": "A brand that uses the same icon",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["title"],
|
"required": ["title"],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -15,3 +15,4 @@
|
|||||||
!sdk.mjs
|
!sdk.mjs
|
||||||
!sdk.js
|
!sdk.js
|
||||||
!sdk.d.ts
|
!sdk.d.ts
|
||||||
|
!.jsonschema.json
|
||||||
|
@ -458,7 +458,7 @@ A SDK is included in the `simple-icons/sdk` entrypoint of the npm package to mak
|
|||||||
```typescript
|
```typescript
|
||||||
import { getIconsData, type IconData } from 'simple-icons/sdk';
|
import { getIconsData, type IconData } from 'simple-icons/sdk';
|
||||||
|
|
||||||
const iconsData: IconData[] = getIconsData();
|
const iconsData: Promise<IconData[]> = getIconsData();
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -466,6 +466,6 @@ import { getIconsData } from 'simple-icons/sdk';
|
|||||||
|
|
||||||
/* @typedef {import("./simple-icons/sdk").IconData} IconData */
|
/* @typedef {import("./simple-icons/sdk").IconData} IconData */
|
||||||
|
|
||||||
/* @type {IconData[]} */
|
/* @type {Promise<IconData[]>} */
|
||||||
const iconsData = getIconsData();
|
const iconsData = getIconsData();
|
||||||
```
|
```
|
||||||
|
@ -7,11 +7,11 @@ import {search} from 'fast-fuzzy';
|
|||||||
import getRelativeLuminance from 'get-relative-luminance';
|
import getRelativeLuminance from 'get-relative-luminance';
|
||||||
import autocomplete from 'inquirer-autocomplete-standalone';
|
import autocomplete from 'inquirer-autocomplete-standalone';
|
||||||
import {
|
import {
|
||||||
URL_REGEX,
|
|
||||||
collator,
|
collator,
|
||||||
getIconsDataString,
|
getIconsDataString,
|
||||||
normalizeColor,
|
normalizeColor,
|
||||||
titleToSlug,
|
titleToSlug,
|
||||||
|
urlRegex,
|
||||||
} from '../sdk.mjs';
|
} from '../sdk.mjs';
|
||||||
import {getJsonSchemaData, writeIconsData} from './utils.js';
|
import {getJsonSchemaData, writeIconsData} from './utils.js';
|
||||||
|
|
||||||
@ -30,8 +30,10 @@ const licenseTypes =
|
|||||||
(license) => ({name: license, value: license}),
|
(license) => ({name: license, value: license}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const isValidURL = (input) =>
|
const isValidURL = async (input) => {
|
||||||
URL_REGEX.test(input) || 'Must be a valid and secure (https://) URL.';
|
const regex = await urlRegex();
|
||||||
|
return regex.test(input) || 'Must be a valid and secure (https://) URL.';
|
||||||
|
};
|
||||||
|
|
||||||
const isValidHexColor = (input) =>
|
const isValidHexColor = (input) =>
|
||||||
HEX_REGEX.test(input) || 'Must be a valid hex code.';
|
HEX_REGEX.test(input) || 'Must be a valid hex code.';
|
||||||
|
2
sdk.d.ts
vendored
2
sdk.d.ts
vendored
@ -63,9 +63,9 @@ export type IconData = {
|
|||||||
/* The next code is autogenerated from sdk.mjs */
|
/* The next code is autogenerated from sdk.mjs */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
|
||||||
export const URL_REGEX: RegExp;
|
|
||||||
export const SVG_PATH_REGEX: RegExp;
|
export const SVG_PATH_REGEX: RegExp;
|
||||||
export function getDirnameFromImportMeta(importMetaUrl: string): string;
|
export function getDirnameFromImportMeta(importMetaUrl: string): string;
|
||||||
|
export function urlRegex(jsonschemaPath?: string): Promise<RegExp>;
|
||||||
export function getIconSlug(icon: IconData): string;
|
export function getIconSlug(icon: IconData): string;
|
||||||
export function svgToPath(svg: string): string;
|
export function svgToPath(svg: string): string;
|
||||||
export function titleToSlug(title: string): string;
|
export function titleToSlug(title: string): string;
|
||||||
|
23
sdk.mjs
23
sdk.mjs
@ -33,11 +33,6 @@ const TITLE_TO_SLUG_CHARS_REGEX = new RegExp(
|
|||||||
|
|
||||||
const TITLE_TO_SLUG_RANGE_REGEX = /[^a-z\d]/g;
|
const TITLE_TO_SLUG_RANGE_REGEX = /[^a-z\d]/g;
|
||||||
|
|
||||||
/**
|
|
||||||
* Regex to validate HTTPs URLs.
|
|
||||||
*/
|
|
||||||
export const URL_REGEX = /^https:\/\/[^\s"']+$/;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regex to validate SVG paths.
|
* Regex to validate SVG paths.
|
||||||
*/
|
*/
|
||||||
@ -52,6 +47,24 @@ export const SVG_PATH_REGEX = /^m[-mzlhvcsqtae\d,. ]+$/i;
|
|||||||
export const getDirnameFromImportMeta = (importMetaUrl) =>
|
export const getDirnameFromImportMeta = (importMetaUrl) =>
|
||||||
path.dirname(fileURLToPath(importMetaUrl));
|
path.dirname(fileURLToPath(importMetaUrl));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a regex to validate HTTPs URLs.
|
||||||
|
* @param {String} jsonschemaPath Path to the *.jsonschema.json* file
|
||||||
|
* @returns {Promise<RegExp>} Regex to validate HTTPs URLs
|
||||||
|
*/
|
||||||
|
export const urlRegex = async (
|
||||||
|
jsonschemaPath = path.join(
|
||||||
|
getDirnameFromImportMeta(import.meta.url),
|
||||||
|
'.jsonschema.json',
|
||||||
|
),
|
||||||
|
) => {
|
||||||
|
return new RegExp(
|
||||||
|
JSON.parse(
|
||||||
|
await fs.readFile(jsonschemaPath, 'utf8'),
|
||||||
|
).definitions.url.pattern,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the slug/filename for an icon.
|
* Get the slug/filename for an icon.
|
||||||
* @param {IconData} icon The icon data as it appears in *_data/simple-icons.json*
|
* @param {IconData} icon The icon data as it appears in *_data/simple-icons.json*
|
||||||
|
@ -9,11 +9,11 @@ import {
|
|||||||
SVG_PATH_REGEX,
|
SVG_PATH_REGEX,
|
||||||
collator,
|
collator,
|
||||||
getDirnameFromImportMeta,
|
getDirnameFromImportMeta,
|
||||||
|
getIconsData,
|
||||||
htmlFriendlyToTitle,
|
htmlFriendlyToTitle,
|
||||||
} from './sdk.mjs';
|
} from './sdk.mjs';
|
||||||
|
|
||||||
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
||||||
const dataFile = path.join(__dirname, '_data', 'simple-icons.json');
|
|
||||||
const htmlNamedEntitiesFile = path.join(
|
const htmlNamedEntitiesFile = path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'node_modules',
|
'node_modules',
|
||||||
@ -22,7 +22,7 @@ const htmlNamedEntitiesFile = path.join(
|
|||||||
);
|
);
|
||||||
const svglintIgnoredFile = path.join(__dirname, '.svglint-ignored.json');
|
const svglintIgnoredFile = path.join(__dirname, '.svglint-ignored.json');
|
||||||
|
|
||||||
const data = JSON.parse(await fs.readFile(dataFile, 'utf8'));
|
const icons = await getIconsData();
|
||||||
const htmlNamedEntities = JSON.parse(
|
const htmlNamedEntities = JSON.parse(
|
||||||
await fs.readFile(htmlNamedEntitiesFile, 'utf8'),
|
await fs.readFile(htmlNamedEntitiesFile, 'utf8'),
|
||||||
);
|
);
|
||||||
@ -369,9 +369,7 @@ const config = {
|
|||||||
|
|
||||||
if (_validCodepointsRepr) {
|
if (_validCodepointsRepr) {
|
||||||
const iconName = htmlFriendlyToTitle(iconTitleText);
|
const iconName = htmlFriendlyToTitle(iconTitleText);
|
||||||
const iconExists = data.icons.some(
|
const iconExists = icons.some((icon) => icon.title === iconName);
|
||||||
(icon) => icon.title === iconName,
|
|
||||||
);
|
|
||||||
if (!iconExists) {
|
if (!iconExists) {
|
||||||
reporter.error(
|
reporter.error(
|
||||||
`No icon with title "${iconName}" found in simple-icons.json`,
|
`No icon with title "${iconName}" found in simple-icons.json`,
|
||||||
|
@ -4,7 +4,6 @@ import path from 'node:path';
|
|||||||
import {describe, it} from 'mocha';
|
import {describe, it} from 'mocha';
|
||||||
import {
|
import {
|
||||||
SVG_PATH_REGEX,
|
SVG_PATH_REGEX,
|
||||||
URL_REGEX,
|
|
||||||
getDirnameFromImportMeta,
|
getDirnameFromImportMeta,
|
||||||
titleToSlug,
|
titleToSlug,
|
||||||
} from '../sdk.mjs';
|
} from '../sdk.mjs';
|
||||||
@ -43,7 +42,6 @@ export const testIcon = (icon, subject, slug) => {
|
|||||||
|
|
||||||
it('has the correct "source"', () => {
|
it('has the correct "source"', () => {
|
||||||
assert.equal(subject.source, icon.source);
|
assert.equal(subject.source, icon.source);
|
||||||
assert.match(subject.source, URL_REGEX);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has an "svg" value', () => {
|
it('has an "svg" value', () => {
|
||||||
@ -67,8 +65,6 @@ export const testIcon = (icon, subject, slug) => {
|
|||||||
assert.equal(subject.license.type, icon.license.type);
|
assert.equal(subject.license.type, icon.license.type);
|
||||||
if (icon.license.type === 'custom') {
|
if (icon.license.type === 'custom') {
|
||||||
assert.equal(subject.license.url, icon.license.url);
|
assert.equal(subject.license.url, icon.license.url);
|
||||||
} else {
|
|
||||||
assert.match(subject.license.url, URL_REGEX);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert.equal(subject.license, undefined);
|
assert.equal(subject.license, undefined);
|
||||||
|
Loading…
Reference in New Issue
Block a user