用JavaScript包装文本

我是JavaScript和jQuery的新手。

我在JavaScript中有一个名为str的变量,它包含非常长的文本,类似于

 "A quick brown fox jumps over a lazy dog". 

我想将它包装并通过在正确的位置插入正确的\nbr/标签将其分配给相同的变量str

我不想使用CSS等。你能告诉我如何在JavaScript中使用适当的函数来执行它,它接受str并返回正确的格式化文本吗?

就像是:

 str = somefunction(str, maxchar); 

我尝试了很多但不幸的是没有任何东西出现在我想要的方式! 🙁

任何帮助都感激不尽…

这应该在最近的maxChar空格处插入换行符:

 str = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It w as popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."; str = wordWrap(str, 40); function wordWrap(str, maxWidth) { var newLineStr = "\n"; done = false; res = ''; do { found = false; // Inserts new line at first whitespace of the line for (i = maxWidth - 1; i >= 0; i--) { if (testWhite(str.charAt(i))) { res = res + [str.slice(0, i), newLineStr].join(''); str = str.slice(i + 1); found = true; break; } } // Inserts new line at maxWidth position, the word is too long to wrap if (!found) { res += [str.slice(0, maxWidth), newLineStr].join(''); str = str.slice(maxWidth); } if (str.length < maxWidth) done = true; } while (!done); return res + str; } function testWhite(x) { var white = new RegExp(/^\s$/); return white.test(x.charAt(0)); }; 

这是一个更短的解决方案:

 var str = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 40 chars." var result = stringDivider(str, 40, "
\n"); console.log(result); function stringDivider(str, width, spaceReplacer) { if (str.length>width) { var p=width for (;p>0 && str[p]!=' ';p--) { } if (p>0) { var left = str.substring(0, p); var right = str.substring(p+1); return left + spaceReplacer + stringDivider(right, width, spaceReplacer); } } return str; }

此函数使用递归来解决问题。

我的变种。 它保持单词完整,因此它可能并不总是符合maxChars标准。

 function wrapText(text, maxChars) { var ret = []; var words = text.split(/\b/); var currentLine = ''; var lastWhite = ''; words.forEach(function(d) { var prev = currentLine; currentLine += lastWhite + d; var l = currentLine.length; if (l > maxChars) { ret.push(prev.trim()); currentLine = d; lastWhite = ''; } else { var m = currentLine.match(/(.*)(\s+)$/); lastWhite = (m && m.length === 3 && m[2]) || ''; currentLine = (m && m.length === 3 && m[1]) || currentLine; } }); if (currentLine) { ret.push(currentLine.trim()); } return ret.join("\n"); } 

像这样的许多行为可以使用正则表达式(使用具有最少匹配字符数的非贪婪量词,或具有最大字符数的贪心量词,取决于您需要的行为)来实现。

下面显示了一个非贪婪的全局替换,它在Node V8 REPL中工作,因此您可以看到命令和结果。 但是同样应该在浏览器中工作。

此模式搜索与定义的组匹配的至少10个字符(\ w表示单词字符,\ s表示空白字符),并将模式固定在\ b字边界上。 然后,它使用反向引用将原始匹配替换为附加了换行符的匹配(在这种情况下,可选地替换在括号中的反向引用中未捕获的空格字符)。

 > s = "This is a paragraph with several words in it." 'This is a paragraph with several words in it.' > s.replace(/([\w\s]{10,}?)\s?\b/g, "$1\n") 'This is a \nparagraph \nwith several\nwords in it\n.' 

在原始海报的要求格式中,这看起来像……

 var str = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It w as popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."; function wordWrap(text,width){ var re = new RegExp("([\\w\\s]{" + (width - 2) + ",}?\\w)\\s?\\b", "g") return text.replace(re,"$1\n") } > wordWrap(str,40) 'Lorem Ipsum is simply dummy text of the\nprinting and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s\n, when an unknown printer took a galley of\ntype and scrambled it to make a type specimen\nbook. It has survived not only five centuries\n, but also the leap into electronic typesetting\n, remaining essentially unchanged. It w as popularised in the 1960s with the\nrelease of Letraset sheets containing Lorem\nIpsum passages, and more recently with desktop publishing\nsoftware like Aldus PageMaker including\nversions of Lorem Ipsum.' 

虽然这个问题很老,但到目前为止提供的许多解决方案都比必要的更复杂和昂贵,正如user2257198指出的那样 – 这是完全可以用短的单行正则表达式解决的。

然而,我发现他的解决方案存在一些问题,包括: 最大宽度之后而不是之前包装,打破未明确包含在字符类中的字符,而不考虑现有的换行符,导致段落的开头被中断。

这导致我编写自己的解决方案:

 // Static Width (Plain Regex) const wrap = (s, w) => s.replace( /(?![^\n]{1,32}$)([^\n]{1,32})\s/g, '$1\n' ); // Dynamic Width (Build Regex) const wrap = (s, w) => s.replace( new RegExp(`(?![^\\n]{1,${w}}$)([^\\n]{1,${w}})\\s`, 'g'), '$1\n' ); 

奖金function

  • 处理任何不是换行符的字符(例如代码)。
  • 正确处理现有换行符(例如段落)。
  • 防止将空格推送到换行符的开头。
  • 防止在字符串结尾添加不必要的换行符。

说明

主要概念是简单地找到包含新行[^\n]连续字符序列,直到所需的长度,例如32 {1,32} 。 通过在字符类中使用否定^ ,它更宽松,避免丢失标点之类的东西,否则必须明确添加:

 str.replace(/([^\n]{1,32})/g, '[$1]\n'); // Matches wrapped in [] to help visualise "[Lorem ipsum dolor sit amet, cons] [ectetur adipiscing elit, sed do ] [eiusmod tempor incididunt ut lab] [ore et dolore magna aliqua.] " 

到目前为止,这只将字符串切成32个字符。 它的工作原理是因为它自己的换行插入标记了第一个序列之后的每个序列的开头。

为了打破单词,在贪婪量词{1,32}之后需要一个限定符来阻止它选择以单词中间结尾的序列。 分词char \b可以在新行的开头处产生空格,因此必须使用空格char \s 。 它也必须放在组外,以便它被吃掉,以防止将最大宽度增加1个字符:

 str.replace(/([^\n]{1,32})\s/g, '[$1]\n'); // Matches wrapped in [] to help visualise "[Lorem ipsum dolor sit amet,] [consectetur adipiscing elit, sed] [do eiusmod tempor incididunt ut] [labore et dolore magna] aliqua." 

现在它在限制之前打破了单词,但最后一个单词和句点在最后一个序列中没有匹配,因为没有终止空格。

可以将“或字符串结束”选项(\s|$)添加到空白区域以扩展匹配,但是最好防止匹配最后一行因为它会导致不必要的新内容 -最后插入的行。 为了实现这一点,可以在之前添加完全相同序列的负面预测,但是使用字符串结束字符而不是空白字符:

 str.replace(/(?![^\n]{1,32}$)([^\n]{1,32})\s/g, '[$1]\n'); // Matches wrapped in [] to help visualise "[Lorem ipsum dolor sit amet,] [consectetur adipiscing elit, sed] [do eiusmod tempor incididunt ut] labore et dolore magna aliqua." 

我的版本。 它返回一个行数而不是一个字符串,因为它在你想要使用的行分隔符(如换行符或html BR)上更灵活。

 function wordWrapToStringList (text, maxLength) { var result = [], line = []; var length = 0; text.split(" ").forEach(function(word) { if ((length + word.length) >= maxLength) { result.push(line.join(" ")); line = []; length = 0; } length += word.length + 1; line.push(word); }); if (line.length > 0) { result.push(line.join(" ")); } return result; }; 

要将行数组转换为字符串,请转换为字符串:

 wordWrapToStringList(textToWrap, 80).join('
');

请注意,它只会自动换行,不会打破长话,而且可能不是最快的。

这是基于javabeangrinder解决方案的扩展答案,该解决方案还包含多段输入的文本:

  function wordWrap(str, width, delimiter) { // use this on single lines of text only if (str.length>width) { var p=width for (; p > 0 && str[p] != ' '; p--) { } if (p > 0) { var left = str.substring(0, p); var right = str.substring(p + 1); return left + delimiter + wordWrap(right, width, delimiter); } } return str; } function multiParagraphWordWrap(str, width, delimiter) { // use this on multi-paragraph lines of text var arr = str.split(delimiter); for (var i = 0; i < arr.length; i++) { if (arr[i].length > width) arr[i] = wordWrap(arr[i], width, delimiter); } return arr.join(delimiter); } 
 function GetWrapedText(text, maxlength) { var resultText = [""]; var len = text.length; if (maxlength >= len) { return text; } else { var totalStrCount = parseInt(len / maxlength); if (len % maxlength != 0) { totalStrCount++ } for (var i = 0; i < totalStrCount; i++) { if (i == totalStrCount - 1) { resultText.push(text); } else { var strPiece = text.substring(0, maxlength - 1); resultText.push(strPiece); resultText.push("
"); text = text.substring(maxlength - 1, text.length); } } } return resultText.join(""); }

在使用正则表达式和其他实现寻找完美的解决方案之后。 我决定改正自己。 它并不完美,但对我的情况很好,也许当你的所有文字都是大写的时候它不能正常工作。

 function breakTextNicely(text, limit, breakpoints) { var parts = text.split(' '); var lines = []; text = parts[0]; parts.shift(); while (parts.length > 0) { var newText = `${text} ${parts[0]}`; if (newText.length > limit) { lines.push(`${text}\n`); breakpoints--; if (breakpoints === 0) { lines.push(parts.join(' ')); break; } else { text = parts[0]; } } else { text = newText; } parts.shift(); } if (lines.length === 0) { return text; } else { return lines.join(''); } } var mytext = 'this is my long text that you can break into multiple line sizes'; console.log( breakTextNicely(mytext, 20, 3) ); 

厌倦了正则表达式和难以阅读的function? 您可以使用内置的Array方法来包装文本。 这是一种方法(只需用你想要的长度替换100限制:

 let string = 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.'; string.split(' ').map((value, index, array) => { if (!array.currentLineLength) {array.currentLineLength = 0} array.currentLineLength += value.length+1; if (array.currentLineLength > 100) { array.currentLineLength = value.length; return "\n" + value; } return value; }).join(' '); 

也许你还想在每一行上缩进这个文字? 没问题,您可以在最后一次join后添加:

 .split("\n").map(value => ''.padEnd(20) + value).join("\n");