How to iterate the split result array of a multiline string value in order to reformat certain lines / newlines?

I have a string of data that has line feeds in the middle. For example:

"Product Name \n Product Color \n Product Quantity \n Product Location \n Product Size \n Product Power" 

The Amount of elements in the string could be infinite.

I need to replace the \n with >>>> \n but only when the line numbers are greater than 3 and not the last line. On the last line I need it to say (end)

I have tried map, and I can split and replace, but I'm having trouble iterating through the array to identify the lines that are to be modified. As well as joining them back up once all lines are modified or not.

Input is:

"Retract-A-Banner\n**Template:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n"

Expected Output:

"Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)\n"

Split by \n and recreate your string with the conditions:

  1. if this is the last one so add (end)
  2. if line is greater than 3, add >>>> \n
  3. otherwise a simple \n will be fine

EDIT:

add a check whether the last string is \n, and remove that value from the array.

const str = "Retract-A-Banner\n**Template:\nFull Color\nImprint Information:\nCL: 488 Special Ops Wing\n353 SOW Integrated Resilience Optimization Network\n";

const splitted = str.split('\n');
let output = '';

if (splitted[splitted.length - 1] === '')
  splitted.length--;
  
for (let i = 0; i < splitted.length; i++) {
  if (i + 1 === splitted.length) {
    output += splitted[i] + ' (end)';
  } else if (i >= 2) {
    output += splitted[i] + ' >>>> \n';
  } else {
    output += splitted[i] + '\n';
  }
}

console.log(output);

Actually one does not necessarily need to choose an iterating approach for the .split(/\n/) operation's result array.

The next introduced approach instead works with a straightforward data access (for all the information needed) via ...

  • Array Destructuring and

  • Array.prototype.pop.

And the return value gets assembled on the spot (depending on the last line's value) utilizing ...

  • Template Literals and

  • Array.prototype.join

function parseNewlines(value) {

  const[ line1, line2, ...rest ] = String(value).split(/\n/);
  const lastLine = rest.pop();

  return [
    `${ line1 }\n${ line2 }\n${ rest.join(' >>>> \n') }`,

    (lastLine === '')
      && `(end)\n`
      || ` >>>> \n${ lastLine }(end)`,

  ].join('');
}

const originalTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network
` // be aware of the last line.

const alteredTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network` // be aware of the last line.

// be aware of the last line.
const expectedResult = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)\n`;

// be aware of the last line.
const expectedResultOfAlteredValue = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)`;

console.log(
  `OP's use case ...\n${ parseNewlines(originalTestValue) }`
);
console.log(
  `altered use case ...\n${ parseNewlines(alteredTestValue) }`
);
console.log('\n');

console.log(
  "OP's use case ...\ntest passed ?..",
  (parseNewlines(originalTestValue) === expectedResult)
);
console.log('\n');

console.log(
  "altered use case ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResult)
);
console.log(
  "altered use case and altered expectation ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResultOfAlteredValue)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Nevertheless an iterating approach could be implemented with a classic reduce task.

function parseNewlines(value) {
  return String(value)

    .split(/\n/)
    .reduce((result, line, idx, arr) => {
      return [

        result,
        (idx < (arr.length - 1))

          ? `${ (idx >= 3) && ' >>>> ' || '' }\n${ line }`
          : (line === '')
              && `(end)\n`
              || ` >>>> \n${ line }(end)`,

      ].join('');
    });
}

const originalTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network
` // be aware of the last line.

const alteredTestValue = `Retract-A-Banner
**Template:
Full Color
Imprint Information:
CL: 488 Special Ops Wing
353 SOW Integrated Resilience Optimization Network` // be aware of the last line.

// be aware of the last line.
const expectedResult = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)\n`;

// be aware of the last line.
const expectedResultOfAlteredValue = `Retract-A-Banner\n**Template:\nFull Color >>>> \nImprint Information: >>>> \nCL: 488 Special Ops Wing >>>> \n353 SOW Integrated Resilience Optimization Network(end)`;

console.log(
  `OP's use case ...\n${ parseNewlines(originalTestValue) }`
);
console.log(
  `altered use case ...\n${ parseNewlines(alteredTestValue) }`
);
console.log('\n');

console.log(
  "OP's use case ...\ntest passed ?..",
  (parseNewlines(originalTestValue) === expectedResult)
);
console.log('\n');

console.log(
  "altered use case ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResult)
);
console.log(
  "altered use case and altered expectation ...\ntest passed ?..",
  (parseNewlines(alteredTestValue) === expectedResultOfAlteredValue)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }