async function ghWeb()

in build/generate-contributors.js [94:139]


async function ghWeb() {
  const GH_CONTRIBUTOR_URL = 'https://github.com/apache/echarts-handbook/contributors/master/'
  // All contributors
  const GH_CONTRIBUTOR_LIST_URL = 'https://github.com/apache/echarts-handbook/contributors-list/master/'
  const total = paths.length
  const tasks = new Array(total)
  for (let i = 0; i < total; ++i) {
    ((i) => {
      const path = paths[i].slice(2)
      console.log('fetching contributors of path', path)
      tasks[i] = fetch(GH_CONTRIBUTOR_LIST_URL + path)
        .then(response => response.text())
        .then(async html => {
          let $ = cheerio.load(html)
          let contributors
          const links = $('li > a')
          if (links.length) {
            contributors = links.map((i, link) => $(link).attr('href').slice(1)).toArray()
          } else {
            // for special case, for example, ghost account
            html = await (await fetch(GH_CONTRIBUTOR_URL + path)).text()
            $ = cheerio.load(html)
            let creator = $('span.Link--primary').text()
            if (creator && (creator = creator.trim())) {
              contributors = [creator]
            }
          }
          entries[path] = contributors = contributors || []
          console.log('fetched contributors of path', path, contributors)
        })
        .catch(e => {
          console.error('failed to fetch contributors of path', path, e)
        })
    })(i)
  }
  const results = await Promise.allSettled(tasks)
  const errorCount = results.filter(r => r.status === 'rejected').length
  console.log(`
    All Done!
      ${total} Total, 
      ${total - errorCount} Successful,
      ${errorCount} Errors`
  )
  console.log('\nResults', entries)
  Object.keys(entries).length && writeToFile()
}