aureooms/rejuvenate

View on GitHub
src/lib/lines/replace.js

Summary

Maintainability
A
1 hr
Test Coverage
import {reduce} from '@iterable-iterator/reduce';

import textReplace from '../text/replace.js';

/**
 * Replace full line match.
 *
 * @param {String} current
 * @param {Array} operation
 */
const whole = (current, [pattern, replacement]) => {
    if (pattern instanceof RegExp) {
        const regexp = new RegExp('^' + pattern.source + '$', pattern.flags);
        return current.replace(regexp, replacement);
    }

    if (typeof pattern === 'string') {
        if (typeof replacement === 'string') {
            return current === pattern ? replacement : current;
        }

        throw new Error(
            `whole: Cannot use '${replacement}' as replacement when pattern (${pattern}) is a string.`,
        );
    } else {
        throw new TypeError(`whole: Cannot use pattern '${pattern}'.`);
    }
};

/**
 * Apply all replacement operations to each line of a given file .
 *
 * Uses String.replace semantics. See
 *   - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_function_as_a_parameter
 *
 * @param {Iterable} operations
 * @param {String} path
 * @param {Object} options
 */
async function replaceOne(operations, path, {lines, write, method}) {
    const buffer = [];
    let changed = false;
    for await (const line of lines(path)) {
        const replacedLine = reduce(method, operations, line);
        if (replacedLine !== line) changed = true;
        buffer.push(replacedLine);
    }

    if (changed && write) {
        const replaced = buffer.join('\n');
        await write(path, replaced ? replaced + '\n' : '');
    }
}

/**
 * Apply {@link replaceOne} to all given paths.
 *
 * @param {Array} operations
 * @param {Iterable} paths
 * @param {Object} options
 */
export default async function replace(operations, paths, options) {
    for await (const path of paths) {
        await replaceOne(operations, path, options);
    }
}

replace.first = textReplace.first;
replace.all = textReplace.all;
replace.whole = whole;