<commit_before>import { listFormatData } from './data.js';

// http://cldr.unicode.org/development/development-process/design-proposals/list-formatting

function getStyle({ style }) {
  if (!style) {
    return 'regular';
  }
  if (['regular', 'duration', 'duration-short', 'duration-narrow'].indexOf(style) < 0) {
    throw new RangeError('Not a valid style: ' + JSON.stringify(style));
  }
  return style;
}


export default class ListFormat {
  constructor(locales, options = {}) {
    this.locale = locales ? locales[0] : 'en-US';
    this.style = getStyle(options);

    this._templates = listFormatData[this.locale][this.style];
  }

  static supportedLocalesOf(locales, options = {}) {
  }

  resolvedOptions() {
    return {
      locale: this.locale,
      style: this.style
    };
  }

  format(list) {
    const length = list.length;

    if (length === 0) {
      return ''; 
    }

    if (length === 1) {
      return list[0];
    }

    if (length === 2) {
      const template = this._templates['2'];
      return template.replace(/\{([0-9])\}/g, (m, v) => {
        return list[parseInt(v)]
      });
    }

    let string = this._templates['end'];
    
    string = string.replace('{1}', list[length - 1]);
    string = string.replace('{0}', list[length - 2]);

    for (let i = length - 3; i >= 0; i--) {
      const template = this._templates[i === 0 ? 'start' : 'middle'];

      string = template.replace(/\{([0-9])\}/g, (m, v) => {
        if (v === '0') {
          return list[i];
        }
        if (v === '1') {
          return string;
        }
      });
    }

    return string;
  }
};

/*global ClobberIntlLocale:false */

if (typeof Intl === 'undefined') {
    if (typeof global !== 'undefined') {
        global.Intl = { ListFormat };
    } else if (typeof window !== 'undefined') {
        window.Intl = { ListFormat };
    } else {
        this.Intl = { ListFormat };
    }
} else if (!Intl.ListFormat || (typeof ClobberIntlListFormat !== 'undefined' &&
      ClobberIntlListFormat)) {
    Intl.ListFormat = ListFormat;
} else if (typeof console !== 'undefined') {
    console.warn('Intl.ListFormat already exists, and has NOT been replaced by this polyfill');
    console.log('To force, set a global ClobberIntlListFormat = true');
}<commit_msg>Update the polyfill to support formatToParts<commit_after>import { listFormatData } from './data.js';

// http://cldr.unicode.org/development/development-process/design-proposals/list-formatting

function getStyle({ type, style }) {
  if (!type) {
    return 'regular';
  }
  if (['regular', 'duration'].indexOf(type) < 0) {
    throw new RangeError('Not a valid style: ' + JSON.stringify(style));
  }
  if (type === 'regular') {
    return 'regular';
  }
  return `duration-${style}`;
}

function deconstructPattern(pattern, placeables) {
  const parts = pattern.split(/\{([^\}]+)\}/);
  const result = [];

  parts.forEach((part, i) => {
    if (i % 2 === 0) {
      if (part.length > 0) {
        result.push({type: 'literal', value: part});
      }
    } else {
      const subst = placeables[part];
      if (!subst) {
        throw new Error(`Missing placeable: "${part}"`);
      }
      if (Array.isArray(subst)) {
        result.push(...subst);
      } else {
        result.push(subst);
      }
    }
  });
  return result;
}

function constructParts(pattern, list) {
  if (list.length === 1) {
    return [{type: 'element', value: list[0]}];
  }

  const elem0 = typeof list[0] === 'string' ?
    {type: 'element', value: list[0]} : list[0];

  let elem1;

  if (list.length === 2) {
    if (typeof list[1] === 'string') {
      elem1 = {type: 'element', value: list[1]}; 
    } else {
      elem1 = list[1];
    }
  } else {
    elem1 = constructParts(pattern, list.slice(1));
  }

  return deconstructPattern(pattern, {
    '0': elem0,
    '1': elem1
  });
}

function FormatToParts(templates, list) {
  if (!Array.isArray(list)) {
    return [
      {type: 'element', value: list}
    ];
  }

  const length = list.length;

  if (length === 0) {
    return [
      {type: 'element', value: ''}
    ];
  }

  if (length === 1) {
    return [
      {type: 'element', value: list[0]}
    ];
  }

  if (length === 2) {
    return constructParts(templates['2'], list);
  }

  let parts = constructParts(templates['start'], [
    list[0],
    constructParts(templates['middle'], list.slice(1, -1))
  ]);

  parts = constructParts(templates['end'], [
    parts, 
    list[list.length - 1]
  ]);

  return parts;
}

export default class ListFormat {
  constructor(locales, options = {}) {
    this.locale = locales ? locales[0] : 'en-US';
    this.style = getStyle(options);

    this._templates = listFormatData[this.locale][this.style];
  }

  static supportedLocalesOf(locales, options = {}) {
  }

  resolvedOptions() {
    return {
      locale: this.locale,
      style: this.style
    };
  }

  format(list) {
    return FormatToParts(this._templates, list).reduce(
      (string, part) => string + part.value, '');
  },
  formatToParts(list) {
    return FormatToParts(this._templates, list);
  }
};

/*global ClobberIntlLocale:false */

if (typeof Intl === 'undefined') {
    if (typeof global !== 'undefined') {
        global.Intl = { ListFormat };
    } else if (typeof window !== 'undefined') {
        window.Intl = { ListFormat };
    } else {
        this.Intl = { ListFormat };
    }
} else if (!Intl.ListFormat || (typeof ClobberIntlListFormat !== 'undefined' &&
      ClobberIntlListFormat)) {
    Intl.ListFormat = ListFormat;
} else if (typeof console !== 'undefined') {
    console.warn('Intl.ListFormat already exists, and has NOT been replaced by this polyfill');
    console.log('To force, set a global ClobberIntlListFormat = true');
}

{'fraction_non_alphanumeric': 0.17333101529902642, 'fraction_numerical': 0.009214186369958275, 'mean_word_length': 2.721216041397154, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1496296', 'n_tokens_mistral': 1920, 'n_tokens_neox': 1875, 'n_words': 430}