function loadSupportedDoc()

in dev-utils/bitrot.js [133:224]


function loadSupportedDoc() {
  const docPath = 'docs/supported-technologies.asciidoc';
  var html = fs.readFileSync(docPath, 'utf8');
  var rows = [];
  var state = null; // null | 'thead' | 'tbody'
  html.split(/\n/g).forEach(function (line) {
    if (!line.startsWith('|')) {
      // no op
    } else if (state === null) {
      if (line.startsWith('|===')) {
        state = 'thead';
      }
    } else if (state === 'thead') {
      state = 'tbody';
    } else if (state === 'tbody') {
      if (line.startsWith('|===')) {
        state = null;
      } else {
        // Examples:
        //      |https://www.npmjs.com/package/generic-pool[generic-pool] | ^2.0.0 \|\| ^3.1.0 |Used by a lot of ...
        //      |https://www.npmjs.com/package/bluebird[bluebird] |>=2.0.0 <4.0.0 |
        var escapePlaceholder = '6B1EC7E1-B273-40E9-94C4-197A59B55E24';
        var cells = line
          .trim()
          .slice(1) // remove leading '|'
          .replace(/\\\|/g, escapePlaceholder)
          .split(/\s*\|\s*/g)
          .map((c) => c.replace(new RegExp(escapePlaceholder, 'g'), '|'))
          .filter((c) => c.length > 0);
        rows.push(cells);
      }
    }
  });
  // log.trace({rows}, `${docPath} table rows`)

  // The tables in supported-technologies.asciidoc have the module
  // name in the first column, and version range in the second. There
  // are two forms of the first cell to parse:
  //      [ '<<hapi,@hapi/hapi>>', '>=17.9.0 <20.0.0' ],
  //      [ '<<koa,Koa>> via koa-router or @koa/router', '>=5.2.0 <10.0.0' ],
  //      [ '<<restify,Restify>>', '>=5.2.0' ],
  //      [ '<<lambda,AWS Lambda>>', 'N/A' ],
  //      ['https://www.npmjs.com/package/jade[jade]', '>=0.5.6']
  //
  // The entries in the "Frameworks" table use the names of internal links in
  // these docs. The anchor name is *sometimes* the same name as the npm
  // module, but sometimes not.
  var results = [];
  let match;
  rows.forEach(function (row) {
    if (row[1] === 'N/A') {
      // skip
    } else if (row[0].includes('<<')) {
      match = /^\s*<<([\w-]+),(.*?)>>/.exec(row[0]);
      if (!match) {
        throw new Error(
          `could not parse this table cell text from docs/supported-technologies.asciidoc: ${JSON.stringify(
            row[0],
          )}`,
        );
      }
      var moduleNames;
      if (match[1] === 'nextjs') {
        moduleNames = ['next'];
      } else if (match[2] === '@hapi/hapi') {
        moduleNames = [match[2]];
      } else if (match[2] === '@opentelemetry/api') {
        moduleNames = [match[2]];
      } else if (match[1] === 'koa') {
        moduleNames = ['koa-router', '@koa/router'];
      } else if (match[1] === 'azure-functions') {
        moduleNames = []; // Azure Functions compat isn't about an NPM package version.
      } else {
        moduleNames = [match[1]];
      }
      moduleNames.forEach((n) => {
        results.push({ name: n, versions: row[1] });
      });
    } else {
      match = /^https:\/\/.*\[(.*)\]$/.exec(row[0].trim());
      if (!match) {
        throw new Error(
          `could not parse this table cell text from docs/supported-technologies.asciidoc: ${JSON.stringify(
            row[0],
          )}`,
        );
      }
      results.push({ name: match[1], versions: row[1] });
    }
  });
  return results;
}