tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

update.js (6410B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 // The Compatibility panel detects issues by comparing against official MDN compatibility data
      6 // at https://github.com/mdn/browser-compat-data). It uses a local snapshot of the dataset.
      7 // This dataset needs to be manually synchronized periodically
      8 
      9 // The subsets from the dataset required by the Compatibility panel are:
     10 // * css.properties: https://github.com/mdn/browser-compat-data/tree/master/css
     11 
     12 // The MDN compatibility data is available as a node package ("@mdn/browser-compat-data"),
     13 // which is used here to update `../dataset/css-properties.json`.
     14 
     15 /* eslint-disable mozilla/reject-relative-requires */
     16 
     17 "use strict";
     18 
     19 const compatData = require("@mdn/browser-compat-data");
     20 const { properties } = compatData.css;
     21 
     22 const { TARGET_BROWSER_ID } = require("../constants.js");
     23 const { getCompatTable } = require("../helpers.js");
     24 
     25 // Flatten all CSS properties aliases here so we don't have to do it at runtime,
     26 // which is costly.
     27 flattenAliases(properties);
     28 parseBrowserVersion(properties);
     29 removeUnusedData(properties);
     30 exportData(properties, "css-properties.json");
     31 
     32 /**
     33 * Builds a list of aliases between CSS properties, like flex and -webkit-flex,
     34 * and mutates individual entries in the web compat data store for CSS properties to
     35 * add their corresponding aliases.
     36 */
     37 function flattenAliases(compatNode) {
     38  for (const term in compatNode) {
     39    if (term.startsWith("_")) {
     40      // Ignore exploring if the term is _aliasOf or __compat.
     41      continue;
     42    }
     43 
     44    const compatTable = getCompatTable(compatNode, [term]);
     45    if (compatTable) {
     46      const aliases = findAliasesFrom(compatTable);
     47 
     48      for (const { alternative_name: name, prefix } of aliases) {
     49        const alias = name || prefix + term;
     50        compatNode[alias] = { _aliasOf: term };
     51      }
     52 
     53      if (aliases.length) {
     54        // Make the term accessible as the alias.
     55        compatNode[term]._aliasOf = term;
     56      }
     57    }
     58 
     59    // Flatten deeper node as well.
     60    flattenAliases(compatNode[term]);
     61  }
     62 }
     63 
     64 function findAliasesFrom(compatTable) {
     65  const aliases = [];
     66 
     67  for (const browser in compatTable.support) {
     68    let supportStates = compatTable.support[browser] || [];
     69    supportStates = Array.isArray(supportStates)
     70      ? supportStates
     71      : [supportStates];
     72 
     73    for (const { alternative_name: name, prefix } of supportStates) {
     74      if (!prefix && !name) {
     75        continue;
     76      }
     77 
     78      aliases.push({ alternative_name: name, prefix });
     79    }
     80  }
     81 
     82  return aliases;
     83 }
     84 
     85 function parseBrowserVersion(compatNode) {
     86  for (const term in compatNode) {
     87    if (term.startsWith("_")) {
     88      // Ignore exploring if the term is _aliasOf or __compat.
     89      continue;
     90    }
     91 
     92    const compatTable = getCompatTable(compatNode, [term]);
     93    if (compatTable?.support) {
     94      for (const [browserId, supportItem] of Object.entries(
     95        compatTable.support
     96      )) {
     97        // supportItem is an array when there are info for both prefixed and non-prefixed
     98        // versions. If it's not an array in the original data, transform it into one
     99        // since we'd have to do it in MDNCompatibility at runtime otherwise.
    100        if (!Array.isArray(supportItem)) {
    101          compatTable.support[browserId] = [supportItem];
    102        }
    103        for (const item of compatTable.support[browserId]) {
    104          replaceVersionsInBrowserSupport(item);
    105        }
    106      }
    107    }
    108 
    109    // Handle deeper node as well.
    110    parseBrowserVersion(compatNode[term]);
    111  }
    112 }
    113 
    114 function replaceVersionsInBrowserSupport(browserSupport) {
    115  browserSupport.added = asFloatVersion(browserSupport.version_added);
    116  browserSupport.removed = asFloatVersion(browserSupport.version_removed);
    117 }
    118 
    119 function asFloatVersion(version) {
    120  // `version` is not always a string (can be null, or a boolean) and in such case,
    121  // we want to keep it that way.
    122  if (typeof version !== "string") {
    123    return version;
    124  }
    125 
    126  if (version.startsWith("\u2264")) {
    127    // MDN compatibility data started to use an expression like "≤66" for version.
    128    // We just ignore the character here.
    129    version = version.substring(1);
    130  }
    131 
    132  return parseFloat(version);
    133 }
    134 
    135 /**
    136 * Remove all unused data from the file so it's smaller and faster to load
    137 */
    138 function removeUnusedData(compatNode) {
    139  for (const term in compatNode) {
    140    if (term.startsWith("_")) {
    141      // Ignore exploring if the term is _aliasOf or __compat.
    142      continue;
    143    }
    144 
    145    const compatTable = getCompatTable(compatNode, [term]);
    146 
    147    // A term may only have a `_aliasOf` property (e.g. for word-wrap), so we don't have
    148    // compat data in it directly.
    149    if (compatTable) {
    150      // source_file references the name of the file in the MDN compat data repo where the
    151      // property is handled. We don't make use of it so we can remove it.
    152      delete compatTable.source_file;
    153 
    154      // Not used at the moment. Doesn't seem to have much information anyway
    155      delete compatTable.description;
    156 
    157      if (compatTable?.support) {
    158        for (const [browserId, supportItem] of Object.entries(
    159          compatTable.support
    160        )) {
    161          // Remove any browser we won't handle
    162          if (!TARGET_BROWSER_ID.includes(browserId)) {
    163            delete compatTable.support[browserId];
    164            continue;
    165          }
    166 
    167          // Remove `version_added` and `version_removed`, that are parsed in `replaceVersionsInBrowserSupport`
    168          // and which we don't need anymore.
    169          for (const item of supportItem) {
    170            delete item.version_added;
    171            delete item.version_removed;
    172            // Those might be interesting, but we're not using them at the moment, so let's
    173            // remove them as they can be quite lengthy
    174            delete item.notes;
    175          }
    176        }
    177      }
    178    }
    179 
    180    // Handle deeper node as well.
    181    removeUnusedData(compatNode[term]);
    182  }
    183 }
    184 
    185 function exportData(data, fileName) {
    186  const fs = require("fs");
    187  const path = require("path");
    188 
    189  const content = `${JSON.stringify(data)}`;
    190 
    191  fs.writeFile(
    192    path.resolve(__dirname, "../dataset", fileName),
    193    content,
    194    err => {
    195      if (err) {
    196        console.error(err);
    197      } else {
    198        console.log(`${fileName} downloaded`);
    199      }
    200    }
    201  );
    202 }