def precompute_pantsrefs(soups):
  """Return links for <a pantsmark="foo"> tags. Mutates soups to give needed ids.

  If we see <a pantsref="foo">something</a>, that's a link whose destination is
  a <a pantsmark="foo"> </a> tag, perhaps on some other tag. To stitch these
  together, we scan the docset to find all the pantsmarks. If an pantsmark does not
  yet have an id to anchor, we give it one.

  Return value dictionary maps pantsrefs to locations:
  { "foo": "path/to/foo.html#fooref", "bar": "other/page.html#barref", ...}
  """
  accumulator = {}
  for (page, soup) in soups.items():
    existing_anchors = find_existing_anchors(soup)
    count = 100
    for tag in soup.find_all('a'):
      if not tag.has_attr('pantsmark'):
        continue
      pantsmark = tag['pantsmark']
      if pantsmark in accumulator:
        raise TaskError('pantsmarks are unique but "{}" appears in {} and {}'
                        .format(pantsmark, page, accumulator[pantsmark]))

      # To link to a place "mid-page", we need an HTML anchor.
      # If this tag already has such an anchor, use it.
      # Else, make one up.
      anchor = tag.get('id') or tag.get('name')
      if not anchor:
        anchor = pantsmark
        while anchor in existing_anchors:
          count += 1
          anchor = '{}_{}'.format(pantsmark, count)
        tag['id'] = anchor
        existing_anchors = find_existing_anchors(soup)

      link = '{}.html#{}'.format(page, anchor)
      accumulator[pantsmark] = link
  return accumulator
Return links for <a pantsmark="foo"> tags. Mutates soups to give needed ids.

  If we see <a pantsref="foo">something</a>, that's a link whose destination is
  a <a pantsmark="foo"> </a> tag, perhaps on some other tag. To stitch these
  together, we scan the docset to find all the pantsmarks. If an pantsmark does not
  yet have an id to anchor, we give it one.

  Return value dictionary maps pantsrefs to locations:
  { "foo": "path/to/foo.html#fooref", "bar": "other/page.html#barref", ...}