繁体   English   中英

将纯文本呈现为HTML维护空白 - 不使用<pre>

[英]Rendering Plaintext as HTML maintaining whitespace – without <pre>

给定任何可打印字符的任意文本文件,如何将其转换为完全相同的HTML(具有以下要求)?

  • 除了默认的HTML空格规则之外,不依赖于任何其他规则
    • 没有<pre>标签
    • 没有CSS white-space规则
  • <p>标签很好,但不是必需的( <br /> s和/或<div> s很好)
  • 确切地保留了空白。

    给定以下输入行(忽略错误的自动语法突出显示):

     Line one Line two, indented four spaces 

    浏览器应该使输出完全相同,保持第二行的缩进以及“缩进”和“空格”之间的间隙。 当然,我实际上并不是在寻找等宽输出,而且字体与算法/标记正交。

    给定两行作为完整的输入文件,示例正确的输出将是:

     Line one<br />&nbsp;&nbsp;&nbsp;&nbsp;Line two, indented&nbsp;&nbsp;&nbsp; four spaces 
  • 希望在浏览器中进行软包装。 也就是说,即使输入行比其视口宽(假设单个单词仍然比所述视口缩小),生成的HTML也不应强制用户滚动。

我正在寻找完全定义的算法。 pythonjavascript中实现的加分点。

(请不要只回答我应该使用<pre>标签或CSS white-space规则,因为我的要求使这些选项无法维持。请不要发布未经测试和/或天真的建议,例如“替换所有空格&nbsp; “毕竟,我很肯定解决方案在技术上是可行的 - 这是一个有趣的问题,你不觉得吗?)

在允许浏览器包装长行的同时执行此操作的解决方案是用空格和非中断空格替换两个空格的每个序列。

浏览器将正确渲染所有空格(正常和非断开),同时仍然包裹长行(由于正常空格)。

使用Javascript:

text = html_escape(text); // dummy function
text = text.replace(/\t/g, '    ')
           .replace(/  /g, '&nbsp; ')
           .replace(/  /g, ' &nbsp;') // second pass
                                      // handles odd number of spaces, where we 
                                      // end up with "&nbsp;" + " " + " "
           .replace(/\r\n|\n|\r/g, '<br />');

使用零宽度空格&#8203; )来保留空格并允许文本换行。 基本思想是将每个空间或空间序列与零宽度空间配对。 然后用不间断的空间替换每个空间。 您还需要编码html并添加换行符。

如果你不关心unicode字符,那就太微不足道了。 你可以使用string.replace()

function textToHTML(text)
{
    return ((text || "") + "")  // make sure it is a string;
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/\t/g, "    ")
        .replace(/ /g, "&#8203;&nbsp;&#8203;")
        .replace(/\r\n|\r|\n/g, "<br />");
}

如果白色空间可以包裹,则将每个空间与零宽度空间配对,如上所述。 否则,要将空白区域保持在一起,请将每个空间序列与零宽度空间配对:

    .replace(/ /g, "&nbsp;")
    .replace(/((&nbsp;)+)/g, "&#8203;$1&#8203;")

要编码unicode字符,它会更复杂一些。 你需要迭代字符串:

var charEncodings = {
    "\t": "&nbsp;&nbsp;&nbsp;&nbsp;",
    " ": "&nbsp;",
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    "\n": "<br />",
    "\r": "<br />"
};
var space = /[\t ]/;
var noWidthSpace = "&#8203;";
function textToHTML(text)
{
    text = (text || "") + "";  // make sure it is a string;
    text = text.replace(/\r\n/g, "\n");  // avoid adding two <br /> tags
    var html = "";
    var lastChar = "";
    for (var i in text)
    {
        var char = text[i];
        var charCode = text.charCodeAt(i);
        if (space.test(char) && !space.test(lastChar) && space.test(text[i + 1] || ""))
        {
            html += noWidthSpace;
        }
        html += char in charEncodings ? charEncodings[char] :
        charCode > 127 ? "&#" + charCode + ";" : char;
        lastChar = char;
    }
    return html;
}  

现在,只是一个评论。 如果不使用等宽字体,您将失去一些格式。 考虑这些带有等宽字体的文本行如何形成列:

ten       seven spaces
eleven    four spaces

如果没有等宽字体,您将丢失列:

十七个空间
十一四个空间

似乎修复它的算法将非常复杂。

虽然这并不能完全满足你的所有要求 - 但有一件事它没有处理标签,我使用了以下gem,它将一个wordWrap()方法添加到Javascript String ,在某些情况下做类似的事情你正在描述的内容 - 所以它可能是一个很好的起点,可以提出一些你想要的其他东西。

//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/string/wordwrap [rev. #2]

// String.wordWrap(maxLength: Integer,
//                 [breakWith: String = "\n"],
//                 [cutType: Integer = 0]): String
//
//   Returns an string with the extra characters/words "broken".
//
//     maxLength  maximum amount of characters per line
//     breakWith  string that will be added whenever one is needed to
//                break the line
//     cutType    0 = words longer than "maxLength" will not be broken
//                1 = words will be broken when needed
//                2 = any word that trespasses the limit will be broken

String.prototype.wordWrap = function(m, b, c){
    var i, j, l, s, r;
    if(m < 1)
        return this;
    for(i = -1, l = (r = this.split("\n")).length; ++i < l; r[i] += s)
        for(s = r[i], r[i] = ""; s.length > m; r[i] += s.slice(0, j) + ((s = s.slice(j)).length ? b : ""))
            j = c == 2 || (j = s.slice(0, m + 1).match(/\S*(\s)?$/))[1] ? m : j.input.length - j[0].length
            || c == 1 && m || j.input.length + (j = s.slice(m).match(/^\S*/)).input.length;
    return r.join("\n");
};

我还想评论一下,在我看来,一般情况下,如果涉及标签,你会想要使用等宽字体,因为字的宽度会随着使用的比例字体而变化(使用的结果)制表符非常依赖字体)。

更新 :这是一个稍微更易阅读的版本礼貌的在线JavaScript美化

String.prototype.wordWrap = function(m, b, c) {
    var i, j, l, s, r;
    if (m < 1)
        return this;
    for (i = -1, l = (r = this.split("\n")).length; ++i < l; r[i] += s)
        for (s = r[i], r[i] = ""; s.length > m; r[i] += s.slice(0, j) + ((s =
                s.slice(j)).length ? b : ""))
            j = c == 2 || (j = s.slice(0, m + 1).match(/\S*(\s)?$/))[1] ? m :
            j.input.length - j[0].length || c == 1 && m || j.input.length +
            (j = s.slice(m).match(/^\S*/)).input.length;
    return r.join("\n");
};

如果在项目中使用jQuery库,则非常简单。

只需一行,将asHTml扩展添加到String Class并:

var plain='&lt;a&gt; i am text plain &lt;/a&gt;'
plain.asHtml();
/* '<a> i am text plain </a>' */

演示: http//jsfiddle.net/abdennour/B6vGG/3/

注意:您不必访问DoM。 只需使用jQuery $('<tagName />')构建器设计模式

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM