Refactor JSONSchema and URL checks (#10276)

This commit is contained in:
Álvaro Mondéjar Rubio 2024-05-22 09:13:35 +02:00 committed by GitHub
parent 3e65e780f6
commit 788014313d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 33 additions and 24 deletions

View File

@ -599,9 +599,8 @@
"required": ["type", "url"],
"properties": {
"type": {
"description": "The license name or 'custom'",
"type": "string",
"enum": ["custom"]
"description": "Custom license type",
"const": "custom"
},
"url": {
"description": "The URL to the license text by the brand",
@ -617,7 +616,7 @@
},
"duplicate": {
"$id": "#duplicate",
"description": "A \"dup\" brand",
"description": "A brand that uses the same icon",
"type": "object",
"required": ["title"],
"properties": {

View File

@ -15,3 +15,4 @@
!sdk.mjs
!sdk.js
!sdk.d.ts
!.jsonschema.json

View File

@ -458,7 +458,7 @@ A SDK is included in the `simple-icons/sdk` entrypoint of the npm package to mak
```typescript
import { getIconsData, type IconData } from 'simple-icons/sdk';
const iconsData: IconData[] = getIconsData();
const iconsData: Promise<IconData[]> = getIconsData();
```
```javascript
@ -466,6 +466,6 @@ import { getIconsData } from 'simple-icons/sdk';
/* @typedef {import("./simple-icons/sdk").IconData} IconData */
/* @type {IconData[]} */
/* @type {Promise<IconData[]>} */
const iconsData = getIconsData();
```

View File

@ -7,11 +7,11 @@ import {search} from 'fast-fuzzy';
import getRelativeLuminance from 'get-relative-luminance';
import autocomplete from 'inquirer-autocomplete-standalone';
import {
URL_REGEX,
collator,
getIconsDataString,
normalizeColor,
titleToSlug,
urlRegex,
} from '../sdk.mjs';
import {getJsonSchemaData, writeIconsData} from './utils.js';
@ -30,8 +30,10 @@ const licenseTypes =
(license) => ({name: license, value: license}),
);
const isValidURL = (input) =>
URL_REGEX.test(input) || 'Must be a valid and secure (https://) URL.';
const isValidURL = async (input) => {
const regex = await urlRegex();
return regex.test(input) || 'Must be a valid and secure (https://) URL.';
};
const isValidHexColor = (input) =>
HEX_REGEX.test(input) || 'Must be a valid hex code.';

2
sdk.d.ts vendored
View File

@ -63,9 +63,9 @@ export type IconData = {
/* The next code is autogenerated from sdk.mjs */
/* eslint-disable */
export const URL_REGEX: RegExp;
export const SVG_PATH_REGEX: RegExp;
export function getDirnameFromImportMeta(importMetaUrl: string): string;
export function urlRegex(jsonschemaPath?: string): Promise<RegExp>;
export function getIconSlug(icon: IconData): string;
export function svgToPath(svg: string): string;
export function titleToSlug(title: string): string;

23
sdk.mjs
View File

@ -33,11 +33,6 @@ const TITLE_TO_SLUG_CHARS_REGEX = new RegExp(
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.
*/
@ -52,6 +47,24 @@ export const SVG_PATH_REGEX = /^m[-mzlhvcsqtae\d,. ]+$/i;
export const getDirnameFromImportMeta = (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.
* @param {IconData} icon The icon data as it appears in *_data/simple-icons.json*

View File

@ -9,11 +9,11 @@ import {
SVG_PATH_REGEX,
collator,
getDirnameFromImportMeta,
getIconsData,
htmlFriendlyToTitle,
} from './sdk.mjs';
const __dirname = getDirnameFromImportMeta(import.meta.url);
const dataFile = path.join(__dirname, '_data', 'simple-icons.json');
const htmlNamedEntitiesFile = path.join(
__dirname,
'node_modules',
@ -22,7 +22,7 @@ const htmlNamedEntitiesFile = path.join(
);
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(
await fs.readFile(htmlNamedEntitiesFile, 'utf8'),
);
@ -369,9 +369,7 @@ const config = {
if (_validCodepointsRepr) {
const iconName = htmlFriendlyToTitle(iconTitleText);
const iconExists = data.icons.some(
(icon) => icon.title === iconName,
);
const iconExists = icons.some((icon) => icon.title === iconName);
if (!iconExists) {
reporter.error(
`No icon with title "${iconName}" found in simple-icons.json`,

View File

@ -4,7 +4,6 @@ import path from 'node:path';
import {describe, it} from 'mocha';
import {
SVG_PATH_REGEX,
URL_REGEX,
getDirnameFromImportMeta,
titleToSlug,
} from '../sdk.mjs';
@ -43,7 +42,6 @@ export const testIcon = (icon, subject, slug) => {
it('has the correct "source"', () => {
assert.equal(subject.source, icon.source);
assert.match(subject.source, URL_REGEX);
});
it('has an "svg" value', () => {
@ -67,8 +65,6 @@ export const testIcon = (icon, subject, slug) => {
assert.equal(subject.license.type, icon.license.type);
if (icon.license.type === 'custom') {
assert.equal(subject.license.url, icon.license.url);
} else {
assert.match(subject.license.url, URL_REGEX);
}
} else {
assert.equal(subject.license, undefined);