diff --git a/.jsonschema.json b/.jsonschema.json index bcdf2eed..46b010e5 100644 --- a/.jsonschema.json +++ b/.jsonschema.json @@ -678,16 +678,7 @@ "sourceUrl": { "$id": "#sourceUrl", "description": "URL for icon source. If is a GitHub URL, is validated to contain a commit hash, to be an issue comment or to be a GitHub organization URL", - "type": "string", - "if": { - "pattern": "^https://github\\.com/(?!(features/actions)|(sponsors)|(logos)$)" - }, - "then": { - "pattern": "^https://github\\.com/[^/]+/[^/]+/(blob/[a-f\\d]{40}/[^\\s]+)|(tree/[a-f\\d]{40}(/[^\\s]+)?)|(((issues)|(pull)|(discussions))/\\d+#((issuecomment)|(discussioncomment))-\\d+)$" - }, - "else": { - "$ref": "#/definitions/url" - } + "$ref": "#/definitions/url" }, "url": { "$id": "#url", diff --git a/_data/simple-icons.json b/_data/simple-icons.json index e744373b..7957a70f 100644 --- a/_data/simple-icons.json +++ b/_data/simple-icons.json @@ -571,7 +571,7 @@ "title": "Alby", "hex": "FFDF6F", "source": "https://github.com/getAlby/media/blob/c24fee4a3f76d6cd000343a972f10590d3913b25/Alby-logo-icons/Alby-logo-head/alby.svg", - "guidelines": "https://github.com/getAlby/lightning-browser-extension/wiki/Open-Design" + "guidelines": "https://github.com/getAlby/lightning-browser-extension/wiki/Open-Design/9e8ebe4d3e7707742d227554c4ee27b29983a1b6" }, { "title": "Alchemy", diff --git a/scripts/lint/ourlint.js b/scripts/lint/ourlint.js index d0df76cf..13c52ad2 100644 --- a/scripts/lint/ourlint.js +++ b/scripts/lint/ourlint.js @@ -105,35 +105,67 @@ const TESTS = { /** * Check if an URL is raw GitHub asset URL. - * @param {string} $url URL instance + * @param {URL} $url URL instance * @returns {boolean} Whether the URL is raw GitHub asset URL */ const isRawGithubAssetUrl = ($url) => $url.hostname === 'raw.githubusercontent.com'; - const allUrlFields = [ - ...new Set( - data.icons.flatMap((icon) => { - /** @type {string[]} */ - const license = - icon.license !== undefined && Object.hasOwn(icon.license, 'url') - ? [ - // eslint-disable-next-line no-warning-comments - // TODO: `hasOwn` is not currently supported by TS. - // See https://github.com/microsoft/TypeScript/issues/44253 - /** @type {string} */ - // @ts-ignore - icon.license.url, - ] - : []; - const guidelines = icon.guidelines ? [icon.guidelines] : []; - return [icon.source, ...guidelines, ...license]; - }), - ), - ]; + /** + * Check if an URL is a GitHub URL. + * @param {URL} $url URL instance + * @returns {boolean} Whether the URL is a GitHub URL + */ + const isGitHubUrl = ($url) => $url.hostname === 'github.com'; + + /** + * Regex to match a permalink GitHub URL for a file. + */ + const permalinkGitHubRegex = + /^https:\/\/github\.com\/[^/]+\/[^/]+\/(blob\/[a-f\d]{40}\/\S+)|(tree\/[a-f\d]{40}(\/\S+)?)|(((issues)|(pull)|(discussions))\/\d+#((issuecomment)|(discussioncomment))-\d+)|(wiki\/\S+\/[a-f\d]{40})$/; + + /** + * URLs excluded from the GitHub URL check as are used by GitHub brands. + */ + const gitHubExcludedUrls = new Set([ + 'https://github.com/logos', + 'https://github.com/features/actions', + 'https://github.com/sponsors', + ]); + + /** + * Check if an URL is a permanent GitHub URL for a file. + * @param {string} url URL string + * @returns {boolean} Whether the URL is a GitHub URL for a file + */ + const isPermalinkGitHubFileUrl = (url) => permalinkGitHubRegex.test(url); + + /** + * Url fields with a boolean indicating if is an icon source URL. + * @type {[boolean, string][]} + */ + const allUrlFields = []; + for (const icon of data.icons) { + allUrlFields.push([true, icon.source]); + if (icon.guidelines) { + allUrlFields.push([false, icon.guidelines]); + } + + if (icon.license !== undefined && Object.hasOwn(icon.license, 'url')) { + allUrlFields.push([ + false, + // eslint-disable-next-line no-warning-comments + // TODO: `hasOwn` is not currently supported by TS. + // See https://github.com/microsoft/TypeScript/issues/44253 + /** @type {string} */ + // @ts-ignore + icon.license.url, + ]); + } + } const invalidUrls = []; - for (const url of allUrlFields) { + for (const [isSourceUrl, url] of allUrlFields) { const $url = new global.URL(url); if (hasRedundantTrailingSlash($url, url)) { @@ -151,6 +183,18 @@ const TESTS = { const expectedUrl = `https://github.com/${owner}/${repo}/blob/${hash}/${directory.join('/')}`; invalidUrls.push(fakeDiff(url, expectedUrl)); } + + if ( + isSourceUrl && + isGitHubUrl($url) && + !isPermalinkGitHubFileUrl(url) && + !gitHubExcludedUrls.has(url) + ) { + invalidUrls.push( + `'${url}' must be a permalink GitHub URL. Expecting something like` + + " 'https://github.com///blob//'.", + ); + } } if (invalidUrls.length > 0) {