Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions api/GPUDevice.json
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@
},
"storageTexture_access_read-write_read-only": {
"__compat": {
"description": "<code>read-write</code> and <code>read-only</code> <code>storageTexture.access</code>",
"description": "`read-write` and `read-only` `storageTexture.access`",
"spec_url": "https://gpuweb.github.io/gpuweb/wgsl/#memory-access-mode",
"tags": [
"web-features:webgpu"
Expand Down Expand Up @@ -424,7 +424,7 @@
},
"texture_rgb10a2uint": {
"__compat": {
"description": "<code>rgb10a2uint</code> texture format",
"description": "`rgb10a2uint` texture format",
"spec_url": "https://gpuweb.github.io/gpuweb/#dom-gputextureformat-rgb10a2uint",
"tags": [
"web-features:webgpu"
Expand Down Expand Up @@ -1312,7 +1312,7 @@
},
"texture_rgb10a2uint": {
"__compat": {
"description": "<code>rgb10a2uint</code> texture format",
"description": "`rgb10a2uint` texture format",
"spec_url": "https://gpuweb.github.io/gpuweb/#dom-gputextureformat-rgb10a2uint",
"tags": [
"web-features:webgpu"
Expand Down Expand Up @@ -1399,7 +1399,7 @@
},
"vertex_unorm10-10-10-2": {
"__compat": {
"description": "<code>unorm10-10-10-2</code> vertex format",
"description": "`unorm10-10-10-2` vertex format",
"spec_url": "https://gpuweb.github.io/gpuweb/#dom-gpuvertexformat-unorm10-10-10-2",
"tags": [
"web-features:webgpu"
Expand Down Expand Up @@ -1641,7 +1641,7 @@
},
"texture_rgb10a2uint": {
"__compat": {
"description": "<code>rgb10a2uint</code> texture format",
"description": "`rgb10a2uint` texture format",
"spec_url": "https://gpuweb.github.io/gpuweb/#dom-gputextureformat-rgb10a2uint",
"tags": [
"web-features:webgpu"
Expand Down Expand Up @@ -1728,7 +1728,7 @@
},
"vertex_unorm10-10-10-2": {
"__compat": {
"description": "<code>unorm10-10-10-2</code> vertex format",
"description": "`unorm10-10-10-2` vertex format",
"spec_url": "https://gpuweb.github.io/gpuweb/#dom-gpuvertexformat-unorm10-10-10-2",
"tags": [
"web-features:webgpu"
Expand Down Expand Up @@ -1977,7 +1977,7 @@
},
"texture_rgb10a2uint": {
"__compat": {
"description": "<code>rgb10a2uint</code> texture format",
"description": "`rgb10a2uint` texture format",
"spec_url": "https://gpuweb.github.io/gpuweb/#dom-gputextureformat-rgb10a2uint",
"tags": [
"web-features:webgpu"
Expand Down Expand Up @@ -2207,7 +2207,7 @@
},
"color_space_display-p3": {
"__compat": {
"description": "<code>display-p3</code> color space",
"description": "`display-p3` color space",
"tags": [
"web-features:webgpu"
],
Expand Down
2 changes: 1 addition & 1 deletion api/GPUTexture.json
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@
},
"texture_rgb10a2uint": {
"__compat": {
"description": "<code>rgb10a2uint</code> texture format",
"description": "`rgb10a2uint` texture format",
"spec_url": "https://gpuweb.github.io/gpuweb/#dom-gputextureformat-rgb10a2uint",
"tags": [
"web-features:webgpu"
Expand Down
18 changes: 9 additions & 9 deletions api/Notification.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"chrome_android": {
"version_added": "42",
"partial_implementation": true,
"notes": "A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'><code>ServiceWorkerRegistration.showNotification()</code></a>."
"notes": "A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'>`ServiceWorkerRegistration.showNotification()`</a>."
},
"edge": {
"version_added": "14"
Expand Down Expand Up @@ -56,8 +56,8 @@
"version_added": "16.4",
"partial_implementation": true,
"notes": [
"The <code>Notification</code> interface is undefined, unless the page is a web app saved to the home screen. The app's manifest must have a non-default <code>display</code> value.",
"A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'><code>ServiceWorkerRegistration.showNotification()</code></a>."
"The `Notification` interface is undefined, unless the page is a web app saved to the home screen. The app's manifest must have a non-default `display` value.",
"A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'>`ServiceWorkerRegistration.showNotification()`</a>."
]
},
"samsunginternet_android": {
Expand Down Expand Up @@ -98,8 +98,8 @@
"version_added": "42",
"partial_implementation": true,
"notes": [
"A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'><code>ServiceWorkerRegistration.showNotification()</code></a>.",
"This constructor always throws a <code>TypeError</code> exception."
"A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'>`ServiceWorkerRegistration.showNotification()`</a>.",
"This constructor always throws a `TypeError` exception."
]
},
"edge": {
Expand Down Expand Up @@ -127,8 +127,8 @@
"version_added": "16.4",
"partial_implementation": true,
"notes": [
"This constructor throws a <code>ReferenceError</code> exception, unless the page is a web app saved to the home screen. The app's manifest must have a non-default <code>display</code> value.",
"A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'><code>ServiceWorkerRegistration.showNotification()</code></a>."
"This constructor throws a `ReferenceError` exception, unless the page is a web app saved to the home screen. The app's manifest must have a non-default `display` value.",
"A notification can only be sent from a service worker. To show a notification, see <a href='https://developer.mozilla.org/docs/Web/API/ServiceWorkerRegistration/showNotification'>`ServiceWorkerRegistration.showNotification()`</a>."
]
},
"samsunginternet_android": "mirror",
Expand Down Expand Up @@ -891,7 +891,7 @@
"safari_ios": {
"version_added": "16.4",
"partial_implementation": true,
"notes": "The parent <code>Notification</code> interface is undefined unless the page is a web app saved to the home screen. The app's manifest must have a non-default <code>display</code> value."
"notes": "The parent `Notification` interface is undefined unless the page is a web app saved to the home screen. The app's manifest must have a non-default `display` value."
},
"samsunginternet_android": "mirror",
"webview_android": {
Expand Down Expand Up @@ -998,7 +998,7 @@
"safari_ios": {
"version_added": "16.4",
"partial_implementation": true,
"notes": "The parent <code>Notification</code> interface is undefined unless the page is a web app saved to the home screen. The app's manifest must have a non-default <code>display</code> value."
"notes": "The parent `Notification` interface is undefined unless the page is a web app saved to the home screen. The app's manifest must have a non-default `display` value."
},
"samsunginternet_android": "mirror",
"webview_android": {
Expand Down
4 changes: 2 additions & 2 deletions api/_globals/performance.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"version_added": "8.5.0",
"version_removed": "16.0.0",
"partial_implementation": true,
"notes": "Available as a part of the <code>perf_hooks</code> module."
"notes": "Available as a part of the `perf_hooks` module."
}
],
"oculus": "mirror",
Expand Down Expand Up @@ -87,7 +87,7 @@
"version_added": "11.7.0",
"version_removed": "16.0.0",
"partial_implementation": true,
"notes": "Available as a part of the <code>perf_hooks</code> module."
"notes": "Available as a part of the `perf_hooks` module."
}
],
"oculus": "mirror",
Expand Down
2 changes: 2 additions & 0 deletions lint/fix.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import fixFeatureOrder from './fixer/feature-order.js';
import fixPropertyOrder from './fixer/property-order.js';
import fixStatementOrder from './fixer/statement-order.js';
import fixDescriptions from './fixer/descriptions.js';
import fixNotes from './fixer/notes.js';
import fixFlags from './fixer/flags.js';
import fixLinks from './fixer/links.js';
import fixMDNURLs from './fixer/mdn-urls.js';
Expand All @@ -35,6 +36,7 @@ const dirname = fileURLToPath(new URL('.', import.meta.url));
/** @type {Readonly<Record<string, function(string, string): Promise<string> | string>>} */
const FIXES = Object.freeze({
descriptions: fixDescriptions,
notes: fixNotes,
common_errors: fixCommonErrors,
flags: fixFlags,
links: fixLinks,
Expand Down
48 changes: 48 additions & 0 deletions lint/fixer/notes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* This file is a part of @mdn/browser-compat-data
* See LICENSE file for more information. */

import { replaceCodeTagsWithBackticks } from '../utils.js';
import walk from '../../utils/walk.js';

/**
* @param {string | string[]} notes
* @returns {string | string[]}
*/
export const fixNotes = (notes) => {
if (Array.isArray(notes)) {
return notes.map(replaceCodeTagsWithBackticks);
}
return replaceCodeTagsWithBackticks(notes);
};

/**
* Fixes HTML in notes that should use Markdown syntax instead.
* @param {string} filename The filename containing compatibility info
* @param {string} actual The current content of the file
* @returns {string} expected content of the file
*/
const fixNotesFixer = (filename, actual) => {
if (filename.includes('/browsers/')) {
return actual;
}

const data = JSON.parse(actual);
const walker = walk(undefined, data);

for (const feature of walker) {
for (const support of Object.values(feature.compat.support)) {
for (const statement of Array.isArray(support) ? support : [support]) {
if (statement.notes) {
statement.notes =
/** @type {string | [string, string, ...string[]]} */ (
fixNotes(statement.notes)
);
}
}
}
}

return JSON.stringify(data, null, 2);
};

export default fixNotesFixer;
36 changes: 36 additions & 0 deletions lint/fixer/notes.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* This file is a part of @mdn/browser-compat-data
* See LICENSE file for more information. */

import assert from 'node:assert/strict';

import { fixNotes } from './notes.js';

describe('fix -> notes', () => {
it('replaces <code> tags with backticks in a string note', () => {
assert.equal(
fixNotes('Before version 90, <code>foo</code> was required.'),
'Before version 90, `foo` was required.',
);
});

it('replaces <code> tags in each note in an array', () => {
assert.deepEqual(
fixNotes([
'Before version 90, <code>foo</code> was required.',
'Use `bar` instead.',
]),
['Before version 90, `foo` was required.', 'Use `bar` instead.'],
);
});

it('leaves notes without <code> tags unchanged', () => {
assert.equal(fixNotes('Use `foo` instead.'), 'Use `foo` instead.');
});

it('does not replace <code> inside backticks', () => {
assert.equal(
fixNotes('The `<code>` element is not supported.'),
'The `<code>` element is not supported.',
);
});
});
14 changes: 14 additions & 0 deletions lint/linter/test-descriptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@

import { styleText } from 'node:util';

import { replaceCodeTagsWithBackticks } from '../utils.js';

import { validateHTML } from './test-notes.js';

export { replaceCodeTagsWithBackticks };

/** @import {Linter, LinterData} from '../types.js' */
/** @import {Logger} from '../utils.js' */
/** @import {CompatStatement} from '../../types/types.js' */
Expand Down Expand Up @@ -117,6 +121,16 @@ export const processData = (data, category, path) => {
}

if (data.description) {
const converted = replaceCodeTagsWithBackticks(data.description);
if (converted !== data.description) {
errors.push({
ruleName: 'no_code_tag_in_description',
path,
actual: data.description,
expected: converted,
});
}

errors.push(...validateHTML(data.description));
}

Expand Down
37 changes: 37 additions & 0 deletions lint/linter/test-descriptions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,41 @@ describe('test-descriptions', () => {
assert.equal(errors.length, 1);
});
});

describe('HTML in descriptions', () => {
it('flags <code> tags as no_code_tag_in_description', () => {
/** @type {CompatStatement} */
const data = {
description: '<code>transient_attachment</code> usage',
support: {},
};
const errors = processData(data, 'api', 'api.Foo.bar');
const err = /** @type {DescriptionError} */ (
errors.find(
(e) =>
typeof e !== 'string' &&
e.ruleName === 'no_code_tag_in_description',
)
);
assert.ok(err);
assert.equal(err.actual, '<code>transient_attachment</code> usage');
assert.equal(err.expected, '`transient_attachment` usage');
});

it('does not flag descriptions without HTML', () => {
/** @type {CompatStatement} */
const data = {
description: '`transient_attachment` usage',
support: {},
};
const errors = processData(data, 'api', 'api.Foo.bar');
assert.ok(
!errors.some(
(e) =>
typeof e !== 'string' &&
e.ruleName === 'no_code_tag_in_description',
),
);
});
});
});
17 changes: 16 additions & 1 deletion lint/linter/test-notes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { styleText } from 'node:util';
import HTMLParser from '@desertnet/html-parser';
import { marked } from 'marked';

import { VALID_ELEMENTS } from '../utils.js';
import { replaceCodeTagsWithBackticks, VALID_ELEMENTS } from '../utils.js';

/** @import {Linter, LinterData} from '../types.js' */
/** @import {Logger} from '../utils.js' */
Expand Down Expand Up @@ -112,6 +112,21 @@ const checkNotes = (notes, browser, feature, logger) => {
logger.error(`Notes for ${styleText('bold', browser)} → ${error}`);
}
}

for (const note of Array.isArray(notes) ? notes : [notes]) {
const converted = replaceCodeTagsWithBackticks(note);
if (converted !== note) {
logger.error(
styleText(
'red',
`Notes for ${styleText('bold', browser)} use HTML code tags instead of backtick-quoted Markdown code
Actual: ${styleText('yellow', `"${note}"`)}
Expected: ${styleText('green', `"${converted}"`)}`,
),
{ fixable: true },
);
}
}
};

/**
Expand Down
Loading
Loading