{"size": 2848, "ext": "js", "max_stars_repo_path": "source/format.js", "max_stars_repo_name": "ryandagg/react-formatted-input", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "source/format.js", "max_issues_repo_name": "ryandagg/react-formatted-input", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "source/format.js", "max_forks_repo_name": "ryandagg/react-formatted-input", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 36.987012987, "max_line_length": 92, "alphanum_fraction": 0.5259831461}
import isRegex from "is-regex";

/**
 * Expand an array of patterns by duplicating those with `repeat` properties
 * @param {Array.<Object>} format An array of patterns
 * @returns {Array.<Object>} An expanded array of patterns (1 per character in value)
 */
function expandFormatRepetitions(format) {
    return format.reduce(function __reducePatterns(patterns, nextItem) {
        if (nextItem.repeat > 1) {
            const expanded = [];
            const copy = { ...nextItem };
            delete copy.repeat;
            for (let i = 0; i < nextItem.repeat; i += 1) {
                expanded.push({ ...copy });
            }
            return [...patterns, ...expanded];
        }
        return [...patterns, nextItem];
    }, []);
}

/**
 * Formatted and raw values post processing
 * @typedef {Object} FormattingResults
 * @property {String} formatted - The formatted value (includes delimiters)
 * @property {String} raw - The raw value (excludes delimiters)
 */

/**
 * Format a value for a pattern
 * @param {String} value The value to format
 * @param {Array.<Object>=} formatSpec The formatting specification to apply to the value
 * @returns {FormattingResults} The formatted and raw values
 */
export function formatValue(value, formatSpec = []) {
    const format = expandFormatRepetitions(formatSpec);
    if (format.length > 0) {
        const characters = value.split("");
        let formattedValue = "",
            rawValue = "";
        while (format.length > 0 && characters.length > 0) {
            const pattern = format.shift();
            if (typeof pattern.char === "object") {
                while (characters.length > 0 && pattern.char.test(characters[0]) !== true) {
                    characters.shift();
                }
                if (characters.length > 0) {
                    formattedValue += characters[0];
                    rawValue += characters[0];
                    characters.shift();
                }
            } else if (typeof pattern.exactly === "string") {
                if (pattern.exactly.length !== 1) {
                    throw new Error(
                        `Unable to format value: 'exactly' value should be of length 1: ${
                            pattern.exactly
                        }`
                    );
                }
                formattedValue += pattern.exactly;
                if (pattern.exactly === characters[0]) {
                    characters.shift();
                }
            } else {
                throw new Error(
                    `Unable to format value: Invalid format specification: ${JSON.stringify(
                        pattern
                    )}`
                );
            }
        }
        return { formatted: formattedValue, raw: rawValue };
    }
    return { formatted: value, raw: value };
}
