5
votes

I want to truncate text by sentences.

Example text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit! Ut vehicula laoreet urna, commodo vulputate massa luctus in. Sed volutpat nunc vitae urna auctor, at tempus enim rhoncus. Morbi ac tortor at arcu mattis commodo? Morbi in ornare arcu, sagittis scelerisque risus. Aenean lobortis lacinia nisl, nec laoreet ipsum viverra ac. Praesent venenatis eleifend risus et pulvinar. Sed vitae nulla sed purus ultrices mattis. Nulla facilisi.'

that's what I have so far:

const truncate = (text: string, limit: number) => {
  const reduced = text
    .split(/[?!\.]/)
    .reduce((acc, cur) => {
      acc = (acc + cur).length < limit? `${acc}. ${cur}` : acc;
      return acc;
    });
 return reduced.length > limit? reduced.slice(limit - 3) + '...' : reduced;
};
console.log(truncate(text, 300));

Problem is it's always put dot instead of that actual punctuation mark what was there before and sometimes it does even put dot at the end.

Here few examples:

limit: 50

1 sentence is 24 in length // 24

2 sentence is 20 in length // 44 <- stop here

3 sentence is 24 in length // 68

Also my code doesn't account sentence length with punctuation but I guess I can just add 1.

Edit:

limit: 70 output: "Lorem ipsum dolor sit amet, consectetur adipiscing elit!"

limit: 40 output: "Lorem ipsum dolor sit amet, consectet..."

limit: 220 output: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua?"

limit: 240 output: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua? Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."

2
What do you want as output? Maybe then I understand what you try to achieve. - Antoni
@Antoni edited my question - henroper

2 Answers

1
votes

Edit: What about this

const string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua? Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

const truncate = (text, limit) => {
  let reduced = text
    .match(/[^\.!\?]+[\.!\?]+/g)
    .reduce((acc, cur) => {
      acc = (acc + cur).length < limit ? acc + cur : acc;
      return acc;
    });
  if (text.match(/[^\.!\?]+[\.!\?]+/g)[0].length > limit) reduced = reduced.slice(0, limit - 3) + "...";
  return reduced;
};
console.log(truncate(string, 240));
0
votes

If i got it correctly you want to split text by actual words. Perhaps this snippet might help.

let string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua? Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

let truncate = (text, limit) => {
  let reduced = text
    .split(/[\s]/);
 return (reduced.length > limit ? reduced.slice(0, limit - 3).join(' ') : reduced.join(' ') ) + '...' ;
};
console.log(truncate(string, 20));
console.log(truncate(string, 30));
console.log(truncate(string, 40));
console.log(truncate(string, 50));
console.log(truncate(string, 60));