Skip to content
Open
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
2 changes: 2 additions & 0 deletions api/Sanitizer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"api": {
"Sanitizer": {
"__compat": {
"mdn_url": "https://developer.mozilla.org/docs/Web/API/Sanitizer",
"spec_url": "https://wicg.github.io/sanitizer-api/#sanitizer",
"tags": [
"web-features:sanitizer"
Expand Down Expand Up @@ -37,6 +38,7 @@
"Sanitizer": {
"__compat": {
"description": "`Sanitizer()` constructor",
"mdn_url": "https://developer.mozilla.org/docs/Web/API/Sanitizer/Sanitizer",
"spec_url": "https://wicg.github.io/sanitizer-api/#dom-sanitizer-sanitizer",
"tags": [
"web-features:sanitizer"
Expand Down
1 change: 1 addition & 0 deletions api/Summarizer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"api": {
"Summarizer": {
"__compat": {
"mdn_url": "https://developer.mozilla.org/docs/Web/API/Summarizer",
"spec_url": "https://webmachinelearning.github.io/writing-assistance-apis/#summarizer",
"tags": [
"web-features:summarizer"
Expand Down
1 change: 1 addition & 0 deletions api/Translator.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"api": {
"Translator": {
"__compat": {
"mdn_url": "https://developer.mozilla.org/docs/Web/API/Translator",
"spec_url": "https://webmachinelearning.github.io/translation-api/#translator",
"tags": [
"web-features:translator"
Expand Down
1 change: 1 addition & 0 deletions api/Viewport.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
},
"segments": {
"__compat": {
"mdn_url": "https://developer.mozilla.org/docs/Web/API/Viewport/segments",
"spec_url": "https://drafts.csswg.org/css-viewport/#dom-viewport-segments",
"tags": [
"web-features:viewport-segments"
Expand Down
51 changes: 50 additions & 1 deletion lint/linter/test-mdn-urls.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import assert from 'node:assert/strict';

/** @import {CompatStatement} from '../../types/types.js' */

import { inventory } from '../../utils/mdn-content-inventory.js';
import {
inventory,
buildSlugByPath,
} from '../../utils/mdn-content-inventory.js';

import { processData, urlsByPath } from './test-mdn-urls.js';

Expand Down Expand Up @@ -253,6 +256,52 @@ describe('test-mdn-urls', () => {
});
});

describe('buildSlugByPath', () => {
it('prefers a page whose browser-compat is a single key over a page that lists it among multiple keys', () => {
const result = buildSlugByPath([
{
frontmatter: {
slug: 'Web/API/Sanitizer/Sanitizer',
'page-type': 'web-api-constructor',
'browser-compat': 'api.Sanitizer.Sanitizer',
},
},
{
frontmatter: {
slug: 'Web/API/SanitizerConfig',
'page-type': 'web-api-interface',
'browser-compat': ['api.Sanitizer.get', 'api.Sanitizer.Sanitizer'],
},
},
]);
assert.equal(
result.get('api.Sanitizer.Sanitizer'),
'Web/API/Sanitizer/Sanitizer',
);
});

it('ignores overview and landing pages', () => {
const result = buildSlugByPath([
{
frontmatter: {
slug: 'Web/API/Foo',
'page-type': 'web-api-overview',
'browser-compat': 'api.Foo',
},
},
{
frontmatter: {
slug: 'Web/API/Foo/bar',
'page-type': 'web-api-instance-method',
'browser-compat': 'api.Foo.bar',
},
},
]);
assert.equal(result.get('api.Foo'), undefined);
assert.equal(result.get('api.Foo.bar'), 'Web/API/Foo/bar');
});
});

describe('mdn_url_duplicate_ancestor', () => {
it('ignores different ancestor mdn_url', () => {
mockInventory({
Expand Down
48 changes: 39 additions & 9 deletions utils/mdn-content-inventory.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,38 @@ const slugs = (() => {
return result;
})();

/** @type {Map<string, string>} BCD path → MDN slug (only unambiguous mappings) */
const slugByPath = (() => {
/** @type {Map<string, string[]>} */
// Page types that are overview/landing pages rather than specific reference pages.
// When a BCD key appears on both one of these and a reference page, the reference page wins.
const OVERVIEW_PAGE_TYPES = new Set([
'web-api-overview',
'guide',
'landing-page',
]);

/**
* Build a map from BCD path to MDN slug, preferring specific reference pages.
* @param {typeof mdnContentInventory.inventory} inventory The MDN content inventory to process
* @returns {Map<string, string>} Map from BCD path to MDN slug
*/
export const buildSlugByPath = (inventory) => {
/**
* @typedef {{ slug: string, isSoleKey: boolean }} SlugEntry
* @type {Map<string, SlugEntry[]>}
*/
const slugsByPath = new Map();
for (const item of mdnContentInventory.inventory) {
for (const item of inventory) {
if (!('browser-compat' in item.frontmatter)) {
continue;
}

if (OVERVIEW_PAGE_TYPES.has(item.frontmatter['page-type'])) {
// Skip overview/landing pages; a reference page for the same BCD key is preferred.
continue;
}

const value = item.frontmatter['browser-compat'];
const paths = Array.isArray(value) ? value : [value];
const isSoleKey = paths.length === 1;

const slug = item.frontmatter.slug;

Expand All @@ -39,19 +60,28 @@ const slugByPath = (() => {
if (!slugsByPath.has(path)) {
slugsByPath.set(path, []);
}
slugsByPath.get(path)?.push(item.frontmatter.slug);
slugsByPath.get(path)?.push({ slug, isSoleKey });
}
}

/** @type {Map<string, string>} */
const result = new Map();
slugsByPath.forEach((values, key) => {
if (values.length === 1) {
result.set(key, values[0]);
slugsByPath.forEach((entries, key) => {
if (entries.length === 1) {
result.set(key, entries[0].slug);
} else {
// When multiple pages list this key, prefer the one where it's the only key.
const soleKeyEntries = entries.filter((e) => e.isSoleKey);
if (soleKeyEntries.length === 1) {
result.set(key, soleKeyEntries[0].slug);
}
Comment on lines +74 to +77
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the last BCD meeting, we agreed to remove this complex part of the heuristic.

}
});
return result;
})();
};

/** @type {Map<string, string>} BCD path → MDN slug (only unambiguous mappings) */
const slugByPath = buildSlugByPath(mdnContentInventory.inventory);

/**
* Mutable inventory data derived from `@ddbeck/mdn-content-inventory`.
Expand Down
Loading