限制每行的字符数并在保留前导空格的同时进行换行

时间:2018-04-02 22:02:04

标签: javascript substring textwrapping

我的目标是:

  • 选择一个文本块(对于此示例,只是一个字符串)。
  • 限制每行的字符数。
  • 保留每行的前导空格,并在文本被包装后重新应用它。

我能够正确限制每行的字符数,但我遇到了空白等问题...

任何帮助将不胜感激

Fiddle

var str = `i am a string that has new lines and whitespace. I need to preserve the leading whitespace and add it back on after the string has been broken up after n characters.

     This line has leading whitespace. Tttttt rrrrrr  
     ttgvgggjjj. Gyjfry bh jkkfrtuj hhdt iihdrtttg.
     Here is another line. Hjkkl gggdetu jcfgjbfftt.
This line has no leading whitespace, so i dont need any reapplied. Jjjxsrg bjlkdetyhk llhfftt`;

function addNewlines(str) { 
    var result = ''; 
    while(str.length > 0) { 
          result += str.substring(0, 25) + '<br />'; 
          str = str.substring(25); 
    } 

    return result; 
}

var newStr = addNewlines(str).toString();
document.getElementById("result").innerHTML = newStr;

应该最终看起来像这样:

i am a string that has ne
w lines and whitespace. I
need to preserve the lea
ding whitespace and add i
t back on after the strin
g has been broken up afte
r n characters. 

   This line has leading
   whitespace. Tttttt rr
   rrrr ttgvgggjjj. Gyjf
   ry bh jkkfrtuj hhdt i
   ihdrtttg. Here is ano
   ther line. Hjkkl gggd
   etu jcfgjbfftt. 

This line has no leading
 whitespace, so i dont n
 eed any reapplied. Jjjx
 srg bjlkdetyhk llhfftt

2 个答案:

答案 0 :(得分:1)

有时候在处理新算法时,使用两次或多次传递要容易得多。所以你想一想它是如何在步骤中起作用而不是一次性的。

我有一个实现工作,有2遍:​​首先我加入段落行,在第二遍我执行实际拆分。

我确信这是一种更好的方法,但这是有效的并且得到充分评论。

我不确定你的ES版本,所以我把它与ES5兼容。

https://jsfiddle.net/2ngtj3aj/

&#13;
&#13;
// Divides a string into chunks of specific size
function chunk(str, size) {
  var chunks = [];
  while(str) { 
    chunks.push(str.substring(0, size));
    str = str.substring(size);
  }
  return chunks;
}

// Removes all spaces from the left of a string
function trimLeft(str) {
  while(str.substr(0,1) == " ") {
    str = str.substr(1);
  }
  return str;
}

// Repeats a character n times
function repeat(c, n) {
  return Array(n + 1).join(c);
}

function addNewlines(str) { 
    var MAX_COLS = 25; // maximum colums on the text
    var DEFAULT_LEADING = 3; // default leading to reapply
    var MIN_LEADING = 1; // minimum amount of spacing to be considered a paragraph
    var CR = "\n";
    var result = '';
    var leading = 0;
    var chunks = [];
    var formattedLines = []; // store the intermediary lines
    var startLeadingSpaceLine = -1; // where does a paragrph start
    var i, l; // counters
    var lines = str.split(CR); // input lines
    
    // In the first pass, we join the paragraph lines
    
    for (i = 0; i < lines.length; i++) {
    
      l = lines[i];
      // If line is empty, we don't use it
      if (l.trim() == "") continue;

      if (l.substr(0, MIN_LEADING) == repeat(" ", MIN_LEADING)) {
        // If line has leading whitespace, remove the leading space
        l = trimLeft(l);
        if (startLeadingSpaceLine > -1) {
          // If we are already on a paragraph,
          // we don't overwrite the flag
        } else {
          // But if this is the first line of an paragraph,
          // We set a flag to allow to join this line with the next one
          // if that contains identation as well
          startLeadingSpaceLine = i;
        }
        // If we are on a paragraph, we don't add this line to the array,
        // first we need to wait to see if we have more lines in the paragraph
        // We also update the line in the array with the whitespace removed
        lines[i] = l;
        continue;
      } else {
        // If line doesn't has whitespace, we check if we have just finished
        // an paragraph
        if (startLeadingSpaceLine > -1) {
          // If we do, then we need to add the previous lines to the array
          // Note: if we want to leave a space between lines, we need to use
          // join(' ') instead of join('')
          var paragraphLines = lines.slice(startLeadingSpaceLine, i).join('');
          // We add the whitespace we like
          paragraphLines = repeat(" ", DEFAULT_LEADING) + paragraphLines;
          formattedLines.push(paragraphLines);
        }
        
      }
      formattedLines.push(l);
    }
    
    // Now we parse again the lines, this time we will divide
    // the lines into chunks
    
    for (i = 0; i < formattedLines.length; i++) {
    
      l = formattedLines[i];

      // Now check against DEFAULT_LEADAING since we have already changed
      // the identation
      if (l.substr(0, DEFAULT_LEADING) == repeat(" ", DEFAULT_LEADING)) {
        
        // If line has leading whitespace, remove the leading space
        // We aded it before just to be able to detect the paragraph.
        l = trimLeft(l);
        
        // Divide the line into chunks. We take into account the space
        // we have removed, otherwise the paragraph will bleed to the
        // right.
        l = chunk(l, MAX_COLS - DEFAULT_LEADING);
        
        // We add leading space to all paragraph lines
        for(var j = 0; j < l.length; j++) {
          l[j] = repeat(" ", DEFAULT_LEADING) + l[j];
        }
        
        // Optional: we add blank lines between paragraphs
        l = [" "].concat(l).concat([" "]);
        
      } else {
      
        // If we have a simple line, just divide it into chunks
        l = chunk(l, MAX_COLS);

			}
      
      // Join the lines with newlines and add to the result
      l = l.join(CR);
      result += l + CR;
    }
    
    
    return result; 
}

var process = function() {
	var newStr = addNewlines(input.value).toString();
	document.getElementById("result").innerHTML = newStr;
}

var input = document.getElementById("input");
input.addEventListener("change", process);
input.addEventListener("keyup", process);
process();
&#13;
<h3>RESULTS</h3>

<textarea id="input" rows="10" cols="80">i am a string that has new lines and whitespace. I need to preserve the leading whitespace and add it back on after the string has been broken up after n characters.

     This line has leading whitespace. Tttttt rrrrrr  
     ttgvgggjjj. Gyjfry bh jkkfrtuj hhdt iihdrtttg.
     Here is another line. Hjkkl gggdetu jcfgjbfftt.
This line has no leading whitespace, so i dont need any reapplied. Jjjxsrg bjlkdetyhk llhfftt</textarea>
<pre id="result"></pre>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

一般逻辑

您的字符串已包含所有空格。如果你将console.log(newStr)添加到你的脚本并查看你的控制台,你会发现这些空格已经存在。

您可能希望删除所有尾随空格(新行字符开始之前的空格)。你可以使用正则表达式替换var newStr = addNewlines(str).toString().replace(/\s+(?=\n)/g, "");

此外,由于所有制表符(&#34; \ t&#34;)将被识别为仅1个字符,但占用的空间比其他字符多,您可能希望用3或4个空格替换它们。像.replace(/\t/g, " ")

这样的东西

需要考虑的另一件事是之前已经存在的新行。你想要停止在那里计数并在已经存在的换行符之后开始一个新的计数器。

在Textarea中显示

&#13;
&#13;
var str = `i am a string that has new lines and whitespace. I need to preserve the leading whitespace and add it back on after the string has been broken up after n characters.

			 This line has leading whitespace. Tttttt rrrrrr  
			 ttgvgggjjj. Gyjfry bh jkkfrtuj hhdt iihdrtttg.
			 Here is another line. Hjkkl gggdetu jcfgjbfftt.
		This line has no leading whitespace, so i dont need any reapplied. Jjjxsrg bjlkdetyhk llhfftt`;

function addNewlines(str) { 
  var result = ''; 
  str = str.replace(/\t/g, "   ");
  
  while(str.length > 0) { 
      nPos = str.indexOf("\n");
      len = nPos > 0 && nPos < 25 ? nPos + 1 : 25;

      result += str.substring(0, len) + '\n'; 
      str = str.substring(len); 
  } 

  return result; 
}


var newStr = addNewlines(str).toString().replace(/\s+(?=\n)/g, "");
document.getElementById("result").value = newStr;
&#13;
<textarea id="result"></textarea>
&#13;
&#13;
&#13;

以HTML格式显示

如果要在HTML中显示这些空格,则可以使用CSS属性white-space: pre

&#13;
&#13;
var str = `i am a string that has new lines and whitespace. I need to preserve the leading whitespace and add it back on after the string has been broken up after n characters.

			 This line has leading whitespace. Tttttt rrrrrr  
			 ttgvgggjjj. Gyjfry bh jkkfrtuj hhdt iihdrtttg.
			 Here is another line. Hjkkl gggdetu jcfgjbfftt.
		This line has no leading whitespace, so i dont need any reapplied. Jjjxsrg bjlkdetyhk llhfftt`;

		function addNewlines(str) { 
			var result = ''; 
      str = str.replace(/\t/g, "   ");
			while(str.length > 0) { 
          nPos = str.indexOf("<br />");
          len = nPos > 0 && nPos < 25 ? nPos + 1 : 25;
          
				  result += str.substring(0, len) + '\n'; 
				  str = str.substring(len); 
			} 

			return result; 
		}
    
    
		var newStr = addNewlines(str).toString().replace(/\s+(?=\n)/g, "");
		console.log(newStr);
		document.getElementById("result1").innerHTML = newStr;
		document.getElementById("result2").innerHTML = newStr;
		document.getElementById("result3").innerHTML = newStr;
		document.getElementById("result4").innerHTML = newStr;
		document.getElementById("result5").innerHTML = newStr;
&#13;
div {

font-family: monospace;
}
&#13;
<h1>normal</h1>
	<div id="result1" style="white-space: normal"></div>
    <h1>pre</h1>
	<div id="result2" style="white-space: pre"></div>
    <h1>nowrap</h1>
	<div id="result3" style="white-space: nowrap"></div>
    <h1>pre-wrap</h1>
	<div id="result4" style="white-space: pre-wrap"></div>
    <h1>pre-line</h1>
	<div id="result5" style="white-space: pre-line"></div>
&#13;
&#13;
&#13;

此外,在您的示例中,您使用制表符来缩进行。如果你想要删除那些,那么你必须删除所有那些。你可以使用另一个正则表达式和替换方法,如下所示:var newStr = addNewlines(str).toString().replace(/\s+(?=\n)/g, "").replace(/\t/g, "");