Skip to content

Commit

Permalink
refactor(build): split up document-extractor
Browse files Browse the repository at this point in the history
  • Loading branch information
caugner committed Nov 17, 2022
1 parent 9a46d54 commit 037fa35
Show file tree
Hide file tree
Showing 8 changed files with 834 additions and 842 deletions.
833 changes: 0 additions & 833 deletions build/document-extractor.ts

This file was deleted.

143 changes: 143 additions & 0 deletions build/extract-bcd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import * as bcd from "@mdn/browser-compat-data/types";
import { packageBCD } from "./resolve-bcd";

interface SimpleSupportStatementWithReleaseDate
extends bcd.SimpleSupportStatement {
release_date?: string;
}

export function extractBCD(query: string): {
browsers: bcd.Browsers | null;
data: bcd.Identifier | null;
} {
const { browsers, data }: { browsers: bcd.Browsers; data: bcd.Identifier } =
packageBCD(query);

if (data === undefined) {
return { browsers: null, data: null };
}

// First extract a map of all release data, keyed by (normalized) browser
// name and the versions.
// You'll have a map that looks like this:
//
// 'chrome_android': {
// '28': {
// release_date: '2012-06-01',
// release_notes: '...',
// ...
//
// The reason we extract this to a locally scoped map, is so we can
// use it to augment the `__compat` blocks for the latest version
// when (if known) it was added.
const browserReleaseData = new Map();
for (const [name, browser] of Object.entries(browsers)) {
const releaseData = new Map();
for (const [version, data] of Object.entries(browser.releases || [])) {
if (data) {
releaseData.set(version, data);
}
}
browserReleaseData.set(name, releaseData);
}

for (const block of _extractCompatBlocks(data)) {
for (const [browser, originalInfo] of Object.entries(block.support)) {
// `originalInfo` here will be one of the following:
// - a single simple_support_statement:
// { version_added: 42 }
// - an array of simple_support_statements:
// [ { version_added: 42 }, { prefix: '-moz', version_added: 35 } ]
//
// Standardize the first version to an array of one, so we don't have
// to deal with two different forms below

const infos: SimpleSupportStatementWithReleaseDate[] = Array.isArray(
originalInfo
)
? originalInfo
: [originalInfo];

for (const infoEntry of infos) {
const added =
typeof infoEntry.version_added === "string" &&
infoEntry.version_added.startsWith("≤")
? infoEntry.version_added.slice(1)
: infoEntry.version_added;
if (browserReleaseData.has(browser)) {
if (browserReleaseData.get(browser).has(added)) {
infoEntry.release_date = browserReleaseData
.get(browser)
.get(added).release_date;
}
}
}

infos.sort((a, b) =>
_compareVersions(_getFirstVersion(b), _getFirstVersion(a))
);

block.support[browser] = infos;
}
}

return {
data,
browsers,
};
}

function _getFirstVersion(support: bcd.SimpleSupportStatement): string {
if (typeof support.version_added === "string") {
return support.version_added;
} else if (typeof support.version_removed === "string") {
return support.version_removed;
} else {
return "0";
}
}

function _compareVersions(a: string, b: string) {
const x = _splitVersion(a);
const y = _splitVersion(b);

return _compareNumberArray(x, y);
}

function _compareNumberArray(a: number[], b: number[]): number {
while (a.length || b.length) {
const x = a.shift() || 0;
const y = b.shift() || 0;
if (x !== y) {
return x - y;
}
}

return 0;
}
function _splitVersion(version: string): number[] {
if (version.startsWith("≤")) {
version = version.slice(1);
}

return version.split(".").map(Number);
}

/**
* Recursively extracts `__compat` objects from the `feature` and from all
* nested features at any depth.
*
* @param {bcd.Identifier} feature The feature.
* @returns {bcd.CompatStatement[]} The array of `__compat` objects.
*/
function _extractCompatBlocks(feature: bcd.Identifier): bcd.CompatStatement[] {
const blocks: bcd.CompatStatement[] = [];
for (const [key, value] of Object.entries(feature)) {
if (key === "__compat") {
blocks.push(value as bcd.CompatStatement);
} else if (typeof value === "object") {
blocks.push(..._extractCompatBlocks(value as bcd.Identifier));
}
}
return blocks;
}
Loading

0 comments on commit 037fa35

Please sign in to comment.