用JavaScript包装文本

use*_*685 14 javascript jquery word-wrap

我是JavaScript和jQuery的新手.

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

"A quick brown fox jumps over a lazy dog". 
Run Code Online (Sandbox Code Playgroud)

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

我不想使用CSS等.你能告诉我如何在JavaScript中使用适当的函数来执行此操作str并将正确的格式化文本返回给它吗?

就像是:

str = somefunction(str, maxchar);
Run Code Online (Sandbox Code Playgroud)

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

任何帮助都感激不尽...

小智 23

虽然这个问题很老,但到目前为止提供的许多解决方案都比必要的更复杂和昂贵,正如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'
);
Run Code Online (Sandbox Code Playgroud)

奖金功能

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

说明

主要概念是简单地找到包含新行的连续的字符序列[^\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.]
"
Run Code Online (Sandbox Code Playgroud)

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

为了打破单词,在贪心量词之后需要一个限定符{1,32}来阻止它选择以单词中间结尾的序列.断字字符\b可以在新行的开头处产生空格,因此\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."
Run Code Online (Sandbox Code Playgroud)

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

(\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."
Run Code Online (Sandbox Code Playgroud)

  • 超好的!我一直在寻找这种类型的功能来在文本区域中生成伪两列格式,并且它工作得很好。谢谢。 (2认同)
  • 这很好,但是单词id大于最大值,根本无法捕获。 (2认同)

小智 20

这应该在最近的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 = '';
    while (str.length > maxWidth) {                 
        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);
        }

    }

    return res + str;
}

function testWhite(x) {
    var white = new RegExp(/^\s$/);
    return white.test(x.charAt(0));
};
Run Code Online (Sandbox Code Playgroud)

  • 最后一次返回错误应该返回res + str; (12认同)

jav*_*der 13

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

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, "<br/>\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;
}
Run Code Online (Sandbox Code Playgroud)

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


小智 7

我的版本。它返回一个行数组而不是一个字符串,因为它更灵活地使用您想要使用的行分隔符(如换行符或 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;
};
Run Code Online (Sandbox Code Playgroud)

要将线数组转换为字符串再转换为字符串:

wordWrapToStringList(textToWrap, 80).join('<br/>');
Run Code Online (Sandbox Code Playgroud)

请注意,它只进行自动换行,不会断掉长单词,而且它可能不是最快的。