diff --git a/scripts/fix/index.ts b/scripts/fix/index.ts index 422c171dac1f0d..1c2f6738c6a856 100644 --- a/scripts/fix/index.ts +++ b/scripts/fix/index.ts @@ -15,6 +15,7 @@ import fixPropertyOrder from './property-order.js'; import fixStatementOrder from './statement-order.js'; import fixLinks from './links.js'; import fixStatus from './status.js'; +import fixSupportHistory from './support-history.js'; import fixMirror from './mirror.js'; const dirname = fileURLToPath(new URL('.', import.meta.url)); @@ -47,6 +48,7 @@ const load = async (...files: string[]): Promise => { fixStatementOrder(file); fixLinks(file); fixStatus(file); + fixSupportHistory(file); fixMirror(file); } } else { diff --git a/scripts/fix/support-history.ts b/scripts/fix/support-history.ts new file mode 100644 index 00000000000000..0682e6b8c64bbe --- /dev/null +++ b/scripts/fix/support-history.ts @@ -0,0 +1,43 @@ +/* This file is a part of @mdn/browser-compat-data + * See LICENSE file for more information. */ + +import { readFileSync, writeFileSync, unlinkSync } from 'node:fs'; +import { hasSupportHistory } from '../../test/linter/test-support-history.js'; + +import type { Identifier } from '../../types/types'; + +const check = (data: Identifier) => { + let hasIssue = false; + if (data.__compat && !hasSupportHistory(data.__compat)) { + hasIssue = true; + } + for (const member in data) { + if (member === '__compat') { + continue; + } + if (check(data[member])) { + delete data[member]; + } + } + return hasIssue; +}; + +const fixSupportHistory = (filename: string) => { + const actual = readFileSync(filename, 'utf-8').trim(); + const data = JSON.parse(actual); + + check(data); + const expected = JSON.stringify(data, null, 2); + + let target = data; + while (Object.keys(target).length === 1) { + target = Object.values(target)[0]; + } + if (Object.keys(target).length) { + writeFileSync(filename, expected + '\n', 'utf-8'); + } else { + unlinkSync(filename); + } +}; + +export default fixSupportHistory; diff --git a/test/linter/index.ts b/test/linter/index.ts index 371137d11067e1..4ded6c4ed3554f 100644 --- a/test/linter/index.ts +++ b/test/linter/index.ts @@ -18,6 +18,7 @@ import testSchema from './test-schema.js'; import testSpecURLs from './test-spec-urls.js'; import testStatus from './test-status.js'; import testStyle from './test-style.js'; +import testSupportHistory from './test-support-history.js'; import testVersions from './test-versions.js'; export default new Linters([ @@ -36,5 +37,6 @@ export default new Linters([ testSpecURLs, testStatus, testStyle, + testSupportHistory, testVersions, ]); diff --git a/test/linter/test-support-history.ts b/test/linter/test-support-history.ts new file mode 100644 index 00000000000000..3ba0c42300ec62 --- /dev/null +++ b/test/linter/test-support-history.ts @@ -0,0 +1,45 @@ +/* This file is a part of @mdn/browser-compat-data + * See LICENSE file for more information. */ + +import chalk from 'chalk-template'; +import { Linter, Logger } from '../utils.js'; + +import type { + CompatStatement, + SimpleSupportStatement, +} from '../../types/types'; + +const stringOrArrayIncludes = ( + target: SimpleSupportStatement['notes'], + str: string, +) => { + if (!target) { + return false; + } + if (Array.isArray(target)) { + return target.some((item) => item.includes(str)); + } + return target.includes(str); +}; + +const includesTrackingBug = (statement: SimpleSupportStatement) => + stringOrArrayIncludes(statement.notes, 'crbug.com') || + stringOrArrayIncludes(statement.notes, 'bugzil.la') || + stringOrArrayIncludes(statement.notes, 'webkit.org/b/'); + +export const hasSupportHistory = (compat: CompatStatement) => + Object.values(compat.support).some( + (c) => Array.isArray(c) || !!c.version_added || includesTrackingBug(c), + ); + +export default { + name: 'Support history', + description: + 'Ensure that there are no features where there is no browser support', + scope: 'feature', + check: (logger: Logger, { data }: { data: CompatStatement }) => { + if (!hasSupportHistory(data)) { + logger.error(chalk`No support and no tracking bug`); + } + }, +} as Linter;