Рендеринг текста в HTML, сохраняя пробелы – без
учитывая любой произвольный текстовый файл, полный печатаемых символов, как это можно преобразовать в HTML, который будет отображаться точно так же (со следующими требованиями)?
- не полагается ни на какие, кроме правил HTML пробелов по умолчанию
- нет
<pre>
tag - нет CSS
white-space
правила
- нет
-
<p>
теги в порядке, но не требуются (<br />
и/или<div>
С отлично) -
пробелы поддерживаются точно.
учитывая следующие строки ввода (игнорировать ошибочную подсветку авто синтаксиса):
Line one Line two, indented four spaces
браузер должен отображать вывод точно так же, сохраняя отступ второй строки и разрыв между "отступами" и "пробелами". Конечно, я не ищу моноширинный выход, и шрифт ортогонального алгоритма/разметки.
учитывая две строки как полный входной файл, пример правильного вывода будет:
Line one<br /> Line two, indented four spaces
желательно мягкое обертывание в браузере. То есть полученный HTML не должен заставлять пользователя прокручивать, даже если входные строки шире, чем их видовое окно (при условии, что отдельные слова все еще сужаются, чем указанное видовое окно).
Я ищу полностью определен . бонусные баллы за реализацию в питон или javascript.
(пожалуйста, не просто ответ, что я должен использовать <pre>
теги или CSS white-space
правило, поскольку мои требования делают эти параметры несостоятельными. Пожалуйста, также не публикуйте непроверенные и / или наивные предложения, такие как "заменить все пробелы на
."В конце концов, я уверен, что решение технически возможно - это интересная проблема, не так ли?)
4 ответов
решение для этого, все еще позволяя браузеру перенос длинных строк заменить каждую последовательность из двух пробелов пробелом и пространством без перерыва.
браузер правильно отобразит все пробелы (нормальные и не разрывные), при этом все еще обертывая длинные строки (из-за нормальных пробелов).
Javascript:
text = html_escape(text); // dummy function
text = text.replace(/\t/g, ' ')
.replace(/ /g, ' ')
.replace(/ /g, ' ') // second pass
// handles odd number of spaces, where we
// end up with " " + " " + " "
.replace(/\r\n|\n|\r/g, '<br />');
использовать нулевой ширины пространства (​
), чтобы сохранить пробелы и разрешить перенос текста. Основная идея состоит в том, чтобы соединить каждое пространство или последовательность пространств с пространством нулевой ширины. Затем заменить каждый пробел на неразрывный пробел. Вы также захотите кодировать html и добавлять разрывы строк.
если вас не волнуют символы юникода, это тривиально. Вы можете просто использовать string.replace()
:
function textToHTML(text)
{
return ((text || "") + "") // make sure it is a string;
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/\t/g, " ")
.replace(/ /g, "​ ​")
.replace(/\r\n|\r|\n/g, "<br />");
}
если это нормально для белого пространства, чтобы обернуть, сопряжение каждого пространства с пространство нулевой ширины, как указано выше. В противном случае, чтобы сохранить пробел вместе, соедините каждый последовательность пробелов с пространством нулевой ширины:
.replace(/ /g, " ")
.replace(/(( )+)/g, "​​")
чтобы кодировать символы юникода, это немного сложнее. Вам нужно повторить строку:
var charEncodings = {
"\t": " ",
" ": " ",
"&": "&",
"<": "<",
">": ">",
"\n": "<br />",
"\r": "<br />"
};
var space = /[\t ]/;
var noWidthSpace = "​";
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;
}
теперь, просто комментарий. Без использования шрифтов monospace вы потеряете форматирование. Рассмотрим, как эти строки текста с помощью шрифта monospace образуют столбцы:
ten seven spaces
eleven four spaces
без шрифта monospaced, вы потеряет столбцы:
десять семь пространств
одиннадцать четыре места
кажется, что алгоритм для исправления этого будет очень сложным.
хотя это не совсем соответствует всем вашим требованиям - во-первых, он не обрабатывает вкладки, я использовал следующий драгоценный камень, который добавляет wordWrap()
метод для Javascript String
s, пару раз сделать что - то похожее на то, что вы описываете-так что это может быть хорошей отправной точкой, чтобы придумать что-то, что также делает дополнительные вещи, которые вы хотите.
//+ 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 beautifier:
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 и:
var plain='<a> i am text plain </a>'
plain.asHtml();
/* '<a> i am text plain </a>' */
демо:http://jsfiddle.net/abdennour/B6vGG/3/
Примечание: вам не придется обращаться к DoM . Просто используйте шаблон дизайна builder jQuery
$('<tagName />')