Experemental Plain2Html/Html2Plain convertor (+ jQuery linkify)

This commit is contained in:
RainLoop Team 2014-07-22 03:58:13 +04:00
parent 8cfd52ef12
commit e4333a6f90
18 changed files with 1211 additions and 604 deletions

View file

@ -113,7 +113,6 @@ Globals.oHtmlEditorDefaultConfig = {
'allowedContent': true,
'autoParagraph': false,
'fillEmptyBlocks': false,
'enterMode': window.CKEDITOR.ENTER_BR,
'shiftEnterMode': window.CKEDITOR.ENTER_BR,

View file

@ -1460,6 +1460,7 @@ Utils.settingsSaveHelperSimpleFunction = function (koTrigger, oContext)
return Utils.settingsSaveHelperFunction(null, koTrigger, oContext, 1000);
};
Utils.$div = $('<div></div>');
/**
* @param {string} sHtml
@ -1468,24 +1469,54 @@ Utils.settingsSaveHelperSimpleFunction = function (koTrigger, oContext)
Utils.htmlToPlain = function (sHtml)
{
var
iPos = 0,
iP1 = 0,
iP2 = 0,
iP3 = 0,
iLimit = 0,
sText = '',
sQuoteChar = '> ',
convertBlockquote = function () {
if (arguments && 1 < arguments.length)
splitPlainText = function (sText)
{
var
iLen = 100,
sPrefix = '',
sSubText = '',
sResult = sText,
iSpacePos = 0,
iNewLinePos = 0
;
while (sResult.length > iLen)
{
var sText = $.trim(arguments[1])
.replace(/__bq__start__(.|[\s\S\n\r]*)__bq__end__/gm, convertBlockquote)
;
sSubText = sResult.substring(0, iLen);
iSpacePos = sSubText.lastIndexOf(' ');
iNewLinePos = sSubText.lastIndexOf('\n');
sText = '\n' + sQuoteChar + $.trim(sText).replace(/\n/gm, '\n' + sQuoteChar) + '\n>\n';
if (-1 !== iNewLinePos)
{
iSpacePos = iNewLinePos;
}
return sText.replace(/\n([> ]+)/gm, function () {
return (arguments && 1 < arguments.length) ? '\n' + $.trim(arguments[1].replace(/[\s]/, '')) + ' ' : '';
});
if (-1 === iSpacePos)
{
iSpacePos = iLen;
}
sPrefix += sSubText.substring(0, iSpacePos) + '\n';
sResult = sResult.substring(iSpacePos + 1);
}
return '';
return sPrefix + sResult;
},
convertBlockquote = function (sText) {
sText = splitPlainText($.trim(sText));
sText = '> ' + sText.replace(/\n/gm, '\n> ');
return sText.replace(/(^|\n)([> ]+)/gm, function () {
return (arguments && 2 < arguments.length) ? arguments[1] + $.trim(arguments[2].replace(/[\s]/, '')) + ' ' : '';
});
},
convertDivs = function () {
@ -1494,40 +1525,23 @@ Utils.htmlToPlain = function (sHtml)
var sText = $.trim(arguments[1]);
if (0 < sText.length)
{
sText = sText.replace(/<div[^>]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs);
sText = sText.replace(/<div[^>]*>([\s\S\r\n]*)<\/div>/gmi, convertDivs);
sText = '\n' + $.trim(sText) + '\n';
}
return sText;
}
return '';
},
fixAttibuteValue = function () {
if (arguments && 1 < arguments.length)
{
return '' + arguments[1] + arguments[2].replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
return '';
return (arguments && 1 < arguments.length) ?
'' + arguments[1] + arguments[2].replace(/</g, '&lt;').replace(/>/g, '&gt;') : '';
},
convertLinks = function () {
if (arguments && 1 < arguments.length)
{
var
sName = $.trim(arguments[1])
// sHref = $.trim(arguments[0].replace(/<a [\s\S]*href[ ]?=[ ]?["']?([^"']+).+<\/a>/gmi, '$1'))
;
return sName;
// sName = (0 === trim(sName).length) ? '' : sName;
// sHref = ('mailto:' === sHref.substr(0, 7)) ? '' : sHref;
// sHref = ('http' === sHref.substr(0, 4)) ? sHref : '';
// sHref = (sName === sHref) ? '' : sHref;
// sHref = (0 < sHref.length) ? ' (' + sHref + ') ' : '';
// return (0 < sName.length) ? sName + sHref : sName;
}
return '';
return (arguments && 1 < arguments.length) ? $.trim(arguments[1]) : '';
}
;
@ -1542,25 +1556,67 @@ Utils.htmlToPlain = function (sHtml)
.replace(/<\/tr>/gi, '\n')
.replace(/<hr[^>]*>/gmi, '\n_______________________________\n\n')
.replace(/<img [^>]*>/gmi, '')
.replace(/<div[^>]*>(.|[\s\S\r\n]*)<\/div>/gmi, convertDivs)
.replace(/<div[^>]*>([\s\S\r\n]*)<\/div>/gmi, convertDivs)
.replace(/<blockquote[^>]*>/gmi, '\n__bq__start__\n')
.replace(/<\/blockquote>/gmi, '\n__bq__end__\n')
.replace(/<a [^>]*>(.|[\s\S\r\n]*)<\/a>/gmi, convertLinks)
.replace(/<a [^>]*>([\s\S\r\n]*?)<\/a>/gmi, convertLinks)
.replace(/<\/div>/gi, '\n')
.replace(/&nbsp;/gi, ' ')
.replace(/<[^>]*>/gm, '')
.replace(/&gt;/gi, '>')
.replace(/&lt;/gi, '<')
.replace(/&quot;/gi, '"')
.replace(/&amp;/gi, '&')
.replace(/&\w{2,6};/gi, '')
.replace(/<[^>]*>/gm, '')
;
return sText
sText = Utils.$div.html(sText).text();
sText = sText
.replace(/\n[ \t]+/gm, '\n')
.replace(/[\n]{3,}/gm, '\n\n')
.replace(/__bq__start__(.|[\s\S\r\n]*)__bq__end__/gm, convertBlockquote)
.replace(/&gt;/gi, '>')
.replace(/&lt;/gi, '<')
;
iPos = 0;
iLimit = 100;
while (0 < iLimit)
{
iLimit--;
iP1 = sText.indexOf('__bq__start__', iPos);
if (-1 < iP1)
{
iP2 = sText.indexOf('__bq__start__', iP1 + 5);
iP3 = sText.indexOf('__bq__end__', iP1 + 5);
if ((-1 === iP2 || iP3 < iP2) && iP1 < iP3)
{
sText = sText.substring(0, iP1) +
convertBlockquote(sText.substring(iP1 + 13, iP3)) +
sText.substring(iP3 + 11);
iPos = 0;
}
else if (-1 < iP2 && iP2 < iP3)
{
iPos = iP2 - 1;
}
else
{
iPos = 0;
}
}
else
{
break;
}
}
sText = sText
.replace(/__bq__start__/gm, '')
.replace(/__bq__end__/gm, '')
;
return sText;
};
/**
@ -1569,9 +1625,77 @@ Utils.htmlToPlain = function (sHtml)
*/
Utils.plainToHtml = function (sPlain)
{
return sPlain.toString()
.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;')
.replace(/\r/g, '').replace(/\n/g, '<br />');
sPlain = sPlain.toString().replace(/\r/g, '');
var
bIn = false,
bDo = true,
bStart = true,
aNextText = [],
sLine = '',
iIndex = 0,
aText = sPlain.split("\n")
;
do
{
bDo = false;
aNextText = [];
for (iIndex = 0; iIndex < aText.length; iIndex++)
{
sLine = aText[iIndex];
bStart = '>' === sLine.substr(0, 1);
if (bStart && !bIn)
{
bDo = true;
bIn = true;
aNextText.push('~~~blockquote~~~');
aNextText.push(sLine.substr(1));
}
else if (!bStart && bIn)
{
bIn = false;
aNextText.push('~~~/blockquote~~~');
aNextText.push(sLine);
}
else if (bStart && bIn)
{
aNextText.push(sLine.substr(1));
}
else
{
aNextText.push(sLine);
}
}
if (bIn)
{
bIn = false;
aNextText.push('~~~/blockquote~~~');
}
aText = aNextText;
}
while (bDo);
sPlain = aText.join("\n");
sPlain = sPlain
.replace(/&/g, '&amp;')
.replace(/>/g, '&gt;').replace(/</g, '&lt;')
.replace(/~~~blockquote~~~[\s]*/g, '<blockquote>')
.replace(/[\s]*~~~\/blockquote~~~/g, '</blockquote>')
.replace(/[\-_~]{10,}/g, '<hr />')
.replace(/\n/g, '<br />');
if ($.fn && $.fn.linkify)
{
sPlain = Utils.$div.html(sPlain)
.linkify().find('.linkified').removeClass('linkified').end()
.html();
}
return sPlain;
};
Utils.resizeAndCrop = function (sUrl, iValue, fCallback)

View file

@ -90,7 +90,6 @@ function MessageModel()
this.body = null;
this.plainRaw = '';
this.isRtl = ko.observable(false);
this.isHtml = ko.observable(false);
this.hasImages = ko.observable(false);
this.attachments = ko.observableArray([]);
@ -268,7 +267,6 @@ MessageModel.prototype.clear = function ()
this.attachmentsMainType('');
this.body = null;
this.isRtl(false);
this.isHtml(false);
this.hasImages(false);
this.attachments([]);
@ -342,7 +340,7 @@ MessageModel.prototype.initByJson = function (oJsonMessage)
this.subjectPrefix('');
this.subjectSuffix(this.subject());
}
this.dateTimeStampInUTC(Utils.pInt(oJsonMessage.DateTimeStampInUTC));
this.hasAttachments(!!oJsonMessage.HasAttachments);
this.attachmentsMainType(oJsonMessage.AttachmentsMainType);
@ -861,7 +859,6 @@ MessageModel.prototype.populateByMessageListItem = function (oMessage)
this.moment(oMessage.moment());
this.body = null;
// this.isRtl(oMessage.isRtl());
// this.isHtml(false);
// this.hasImages(false);
// this.attachments([]);
@ -1026,7 +1023,6 @@ MessageModel.prototype.storeDataToDom = function ()
{
if (this.body)
{
this.body.data('rl-is-rtl', !!this.isRtl());
this.body.data('rl-is-html', !!this.isHtml());
this.body.data('rl-has-images', !!this.hasImages());
@ -1055,7 +1051,6 @@ MessageModel.prototype.fetchDataToDom = function ()
{
if (this.body)
{
this.isRtl(!!this.body.data('rl-is-rtl'));
this.isHtml(!!this.body.data('rl-is-html'));
this.hasImages(!!this.body.data('rl-has-images'));

View file

@ -886,7 +886,7 @@ WebMailDataStorage.prototype.setMessage = function (oData, bCached)
oBody = null,
oTextBody = null,
sId = '',
sPlain = '',
sPlainAsHtml = '',
bPgpSigned = false,
bPgpEncrypted = false,
oMessagesBodiesDom = this.messagesBodiesDom(),
@ -922,17 +922,20 @@ WebMailDataStorage.prototype.setMessage = function (oData, bCached)
if (Utils.isNormal(oData.Result.Html) && '' !== oData.Result.Html)
{
bIsHtml = true;
oBody.html(oData.Result.Html.toString()).addClass('b-text-part html');
oBody
.html(oData.Result.Html.toString())
.linkify().find('.linkified').removeClass('linkified').end()
.addClass('b-text-part html')
;
}
else if (Utils.isNormal(oData.Result.Plain) && '' !== oData.Result.Plain)
{
bIsHtml = false;
sPlain = oData.Result.Plain.toString();
sPlainAsHtml = Utils.plainToHtml(oData.Result.Plain.toString());
if ((oMessage.isPgpSigned() || oMessage.isPgpEncrypted()) &&
RL.data().capaOpenPGP() && Utils.isNormal(oData.Result.PlainRaw))
if ((oMessage.isPgpSigned() || oMessage.isPgpEncrypted()) && RL.data().capaOpenPGP())
{
oMessage.plainRaw = Utils.pString(oData.Result.PlainRaw);
oMessage.plainRaw = Utils.pString(oData.Result.Plain);
bPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(oMessage.plainRaw);
if (!bPgpEncrypted)
@ -944,7 +947,7 @@ WebMailDataStorage.prototype.setMessage = function (oData, bCached)
$proxyDiv.empty();
if (bPgpSigned && oMessage.isPgpSigned())
{
sPlain =
sPlainAsHtml =
$proxyDiv.append(
$('<pre class="b-plain-openpgp signed"></pre>').text(oMessage.plainRaw)
).html()
@ -952,7 +955,7 @@ WebMailDataStorage.prototype.setMessage = function (oData, bCached)
}
else if (bPgpEncrypted && oMessage.isPgpEncrypted())
{
sPlain =
sPlainAsHtml =
$proxyDiv.append(
$('<pre class="b-plain-openpgp encrypted"></pre>').text(oMessage.plainRaw)
).html()
@ -965,7 +968,11 @@ WebMailDataStorage.prototype.setMessage = function (oData, bCached)
oMessage.isPgpEncrypted(bPgpEncrypted);
}
oBody.html(sPlain).addClass('b-text-part plain');
oBody
.html(sPlainAsHtml)
.linkify().find('.linkified').removeClass('linkified').end()
.addClass('b-text-part plain')
;
}
else
{
@ -977,12 +984,6 @@ WebMailDataStorage.prototype.setMessage = function (oData, bCached)
oMessage.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None);
oMessage.pgpSignedVerifyUser('');
if (oData.Result.Rtl)
{
oMessage.isRtl(true);
oBody.addClass('rtl-text-part');
}
oMessage.body = oBody;
if (oMessage.body)
{

View file

@ -52,7 +52,7 @@ html.rl-no-preview-pane {
padding-left: 10px;
}
}
.b-message-view-desc {
text-align: center;
font-size: 24px;
@ -316,10 +316,6 @@ html.rl-no-preview-pane {
display: none;
}
&.rtl-text-part {
direction: rtl;
}
&.html {
div[data-x-div-type=body] {
margin: 15px;
@ -345,7 +341,7 @@ html.rl-no-preview-pane {
border: none;
font-family: Monaco, Menlo, Consolas, 'Courier New', monospace;
}
blockquote {
border-left: 2px solid blue;
color: blue;