function collectAllCustomElementsFromICU(icuElements, customElements = new Map()) {
  for (const el of icuElements) {
    if (el.type === TYPE.literal || el.type === TYPE.pound) continue;

    customElements.set(el.value, el);

    // Plurals need to be inspected recursively
    if (el.type === TYPE.plural) {
      // Look at all options of the plural (=1{} =other{}...)
      for (const option of Object.values(el.options)) {
        // Run collections on each option's elements
        collectAllCustomElementsFromICU(option.value, customElements);
      }
    }
  }

  return customElements;
}
Function to retrieve all elements from an ICU message AST that are associated
with a named input, like '{varName}' or '{varName, number, bytes}'. This
differs from literal message types which are just arbitrary text.

This function recursively inspects plural elements for nested elements,
but since the output is a Map they are deduplicated.
e.g. "=1{hello {icu}} =other{hello {icu}}" will produce one element in the output,
with "icu" as its key.

TODO: don't do that deduplication because messages within a plural message could be number
messages with different styles.

@param {Array<MessageFormatElement>} icuElements
@param {Map<string, MessageFormatElement>} [customElements]
@return {Map<string, MessageFormatElement>}