');
}
// replace special characters
var chars = {
'\u2122': '™',
'\xA9': '©',
'\u2026': '…',
'\u2014': '—',
'\u2010': '‐'
};
$.each(chars, function (i, s) {
html = html.replace(new RegExp(i, 'g'), s);
});
html = html.replace(/&/g, '&');
// remove empty paragpraphs
html = html.replace(/<\/p>/gi, "");
// remove new lines
html = html.replace(/\n{2,}/g, "\n");
// remove all newlines
if (this.opts.removeNewlines) {
html = html.replace(/\r?\n/g, "");
}
return html;
},
onPaste: function onPaste(html, data, insert) {
// if paste event
if (insert !== true) {
// remove google docs markers
html = html.replace(/([\w\W]*?)<\/b>/gi, "$2");
html = html.replace(/([\w\W]*?)<\/b>/gi, "$3");
// google docs styles
html = html.replace(/]*(font-style: italic; font-weight: bold|font-weight: bold; font-style: italic)[^>]*>([\w\W]*?)<\/span>/gi, '$2');
html = html.replace(/]*(font-style: italic; font-weight: 700|font-weight: 700; font-style: italic)[^>]*>([\w\W]*?)<\/span>/gi, '$2');
html = html.replace(/]*font-style: italic[^>]*>([\w\W]*?)<\/span>/gi, '$1');
html = html.replace(/]*font-weight: bold[^>]*>([\w\W]*?)<\/span>/gi, '$1');
html = html.replace(/]*font-weight: 700[^>]*>([\w\W]*?)<\/span>/gi, '$1');
var msword = this.clean.isHtmlMsWord(html);
if (msword) {
html = this.clean.cleanMsWord(html);
}
}
html = $.trim(html);
if (data.pre) {
if (this.opts.preSpaces) {
html = html.replace(/\t/g, new Array(this.opts.preSpaces + 1).join(' '));
}
} else {
html = this.clean.replaceBrToNl(html);
html = this.clean.removeTagsInsidePre(html);
}
// if paste event
if (insert !== true) {
html = this.clean.removeEmptyInlineTags(html);
if (data.encode === false) {
html = html.replace(/&/g, '&');
html = this.clean.convertTags(html, data);
html = this.clean.getPlainText(html);
html = this.clean.reconvertTags(html, data);
}
}
if (data.text) {
html = this.clean.replaceNbspToSpaces(html);
html = this.clean.getPlainText(html);
}
if (data.lists) {
html = html.replace("\n", '
');
}
if (data.encode) {
html = this.clean.encodeHtml(html);
}
if (data.paragraphize) {
html = this.paragraphize.load(html);
}
return html;
},
getCurrentType: function getCurrentType(html, insert) {
var blocks = this.selection.blocks();
var data = {
text: false,
encode: false,
paragraphize: true,
line: this.clean.isHtmlLine(html),
blocks: this.clean.isHtmlBlocked(html),
pre: false,
lists: false,
block: true,
inline: true,
links: true,
images: true
};
if (blocks.length === 1 && this.utils.isCurrentOrParent(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'a', 'figcaption'])) {
data.text = true;
data.paragraphize = false;
data.inline = false;
data.images = false;
data.links = false;
data.line = true;
} else if (this.opts.type === 'inline' || this.opts.enterKey === false) {
data.paragraphize = false;
data.block = false;
data.line = true;
} else if (blocks.length === 1 && this.utils.isCurrentOrParent(['li'])) {
data.lists = true;
data.block = false;
data.paragraphize = false;
data.images = false;
} else if (blocks.length === 1 && this.utils.isCurrentOrParent(['th', 'td', 'blockquote'])) {
data.block = false;
data.paragraphize = false;
} else if (this.opts.type === 'pre' || blocks.length === 1 && this.utils.isCurrentOrParent('pre')) {
data.inline = false;
data.block = false;
data.encode = true;
data.pre = true;
data.paragraphize = false;
data.images = false;
data.links = false;
}
if (data.line === true) {
data.paragraphize = false;
}
if (insert === true) {
data.text = false;
}
return data;
},
isHtmlBlocked: function isHtmlBlocked(html) {
var match1 = html.match(new RegExp('(' + this.opts.blockTags.join('|').toUpperCase() + ')>', 'gi'));
var match2 = html.match(new RegExp('
])>', 'gi'));
return match1 === null && match2 === null ? false : true;
},
isHtmlLine: function isHtmlLine(html) {
if (this.clean.isHtmlBlocked(html)) {
return false;
}
var matchBR = html.match(/
/gi);
var matchNL = html.match(/\n/gi);
return !matchBR && !matchNL ? true : false;
},
isHtmlMsWord: function isHtmlMsWord(html) {
return html.match(/class="?Mso|style="[^"]*\bmso-|style='[^'']*\bmso-|w:WordDocument/i);
},
removeEmptyInlineTags: function removeEmptyInlineTags(html) {
var tags = this.opts.inlineTags;
var $div = $("").html($.parseHTML(html, document, true));
var self = this;
var $spans = $div.find('span');
var $tags = $div.find(tags.join(','));
$tags.removeAttr('style');
$tags.each(function () {
var tagHtml = $(this).html();
if (this.attributes.length === 0 && self.utils.isEmpty(tagHtml)) {
$(this).replaceWith(function () {
return $(this).contents();
});
}
});
$spans.each(function () {
var tagHtml = $(this).html();
if (this.attributes.length === 0) {
$(this).replaceWith(function () {
return $(this).contents();
});
}
});
html = $div.html();
// convert php tags
html = html.replace('', '?>');
$div.remove();
return html;
},
cleanMsWord: function cleanMsWord(html) {
html = html.replace(//g, "");
html = html.replace(/[\s\S]*?<\/o:p>/gi, '');
html = html.replace(/\n/g, " ");
html = html.replace(/
|<\/p>|<\/div>|<\/li>|<\/td>/gi, '\n\n');
// lists
var $div = $("").html(html);
var lastList = false;
var lastLevel = 1;
var listsIds = [];
$div.find("p[style]").each(function () {
var matches = $(this).attr('style').match(/mso\-list\:l([0-9]+)\slevel([0-9]+)/);
if (matches) {
var currentList = parseInt(matches[1]);
var currentLevel = parseInt(matches[2]);
var listType = $(this).html().match(/^[\w]+\./) ? "ol" : "ul";
var $li = $("").html($(this).html());
$li.html($li.html().replace(/^([\w\.]+), '<'));
$li.find("span:first").remove();
if (currentLevel == 1 && $.inArray(currentList, listsIds) == -1) {
var $list = $("<" + listType + "/>").attr({ "data-level": currentLevel, "data-list": currentList }).html($li);
$(this).replaceWith($list);
lastList = currentList;
listsIds.push(currentList);
} else {
if (currentLevel > lastLevel) {
var $prevList = $div.find('[data-level="' + lastLevel + '"][data-list="' + lastList + '"]');
var $lastList = $prevList;
for (var i = lastLevel; i < currentLevel; i++) {
$list = $("<" + listType + "/>");
$list.appendTo($lastList.find("li").last());
$lastList = $list;
}
$lastList.attr({ "data-level": currentLevel, "data-list": currentList }).html($li);
} else {
var $prevList = $div.find('[data-level="' + currentLevel + '"][data-list="' + currentList + '"]').last();
$prevList.append($li);
}
lastLevel = currentLevel;
lastList = currentList;
$(this).remove();
}
}
});
$div.find('[data-level][data-list]').removeAttr('data-level data-list');
html = $div.html();
return html;
},
replaceNbspToSpaces: function replaceNbspToSpaces(html) {
return html.replace(' ', ' ');
},
replaceBrToNl: function replaceBrToNl(html) {
return html.replace(/
/gi, '\n');
},
replaceNlToBr: function replaceNlToBr(html) {
return html.replace(/\n/g, '
');
},
convertTags: function convertTags(html, data) {
var $div = $('').html(html);
// remove iframe
$div.find('iframe').remove();
// link target & attrs
var $links = $div.find('a');
$links.removeAttr('style');
if (this.opts.pasteLinkTarget !== false) {
$links.attr('target', this.opts.pasteLinkTarget);
}
// links
if (data.links && this.opts.pasteLinks) {
$div.find('a').each(function (i, link) {
if (link.href) {
var tmp = '##%a href="' + link.href + '"';
var attr;
for (var j = 0, length = link.attributes.length; j < length; j++) {
attr = link.attributes.item(j);
if (attr.name !== 'href') {
tmp += ' ' + attr.name + '="' + attr.value + '"';
}
}
link.outerHTML = tmp + '%##' + link.innerHTML + '##%/a%##';
}
});
}
html = $div.html();
// images
if (data.images && this.opts.pasteImages) {
html = html.replace(/
![]()
])>/gi, '##%img$1src="$2"$3%##');
}
// plain text
if (this.opts.pastePlainText) {
return html;
}
// all tags
var blockTags = data.lists ? ['ul', 'ol', 'li'] : this.opts.pasteBlockTags;
var tags;
if (data.block || data.lists) {
tags = data.inline ? blockTags.concat(this.opts.pasteInlineTags) : blockTags;
} else {
tags = data.inline ? this.opts.pasteInlineTags : [];
}
var len = tags.length;
for (var i = 0; i < len; i++) {
html = html.replace(new RegExp('<\/' + tags[i] + '>', 'gi'), '###/' + tags[i] + '###');
if (tags[i] === 'td' || tags[i] === 'th') {
html = html.replace(new RegExp('<' + tags[i] + '(.*?[^>])((colspan|rowspan)="(.*?[^>])")?(.*?[^>])>', 'gi'), '###' + tags[i] + ' $2###');
} else if (tags[i] === 'span') {
html = html.replace(new RegExp('<' + tags[i] + '([^>]*)class="([^>]*)"[^>]*>', 'gi'), '###' + tags[i] + ' class="$2"###');
html = html.replace(new RegExp('<' + tags[i] + '([^>]*)data-redactor-style-cache="([^>]*)"[^>]*>', 'gi'), '###' + tags[i] + ' cache="$2"###');
} else {
html = html.replace(new RegExp('<' + tags[i] + '[^>]*>', 'gi'), '###' + tags[i] + '###');
}
}
return html;
},
reconvertTags: function reconvertTags(html, data) {
// links & images
if (data.links && this.opts.pasteLinks || data.images && this.opts.pasteImages) {
html = html.replace(new RegExp('##%', 'gi'), '<');
html = html.replace(new RegExp('%##', 'gi'), '>');
}
// plain text
if (this.opts.pastePlainText) {
return html;
}
var blockTags = data.lists ? ['ul', 'ol', 'li'] : this.opts.pasteBlockTags;
var tags;
if (data.block || data.lists) {
tags = data.inline ? blockTags.concat(this.opts.pasteInlineTags) : blockTags;
} else {
tags = data.inline ? this.opts.pasteInlineTags : [];
}
var len = tags.length;
for (var i = 0; i < len; i++) {
html = html.replace(new RegExp('###\/' + tags[i] + '###', 'gi'), '' + tags[i] + '>');
}
for (var i = 0; i < len; i++) {
html = html.replace(new RegExp('###' + tags[i] + '###', 'gi'), '<' + tags[i] + '>');
}
for (var i = 0; i < len; i++) {
if (tags[i] === 'td' || tags[i] === 'th') {
html = html.replace(new RegExp('###' + tags[i] + '\s?(.*?[^#])###', 'gi'), '<' + tags[i] + '$1>');
} else if (tags[i] === 'span') {
html = html.replace(new RegExp('###' + tags[i] + ' cache="(.*?[^#])"###', 'gi'), '<' + tags[i] + ' style="$1" data-redactor-span="true" data-redactor-style-cache="$1">');
html = html.replace(new RegExp('###' + tags[i] + '\s?(.*?[^#])###', 'gi'), '<' + tags[i] + '$1>');
}
}
return html;
},
cleanPre: function cleanPre(block) {
block = typeof block === 'undefined' ? $(this.selection.block()).closest('pre', this.core.editor()[0]) : block;
$(block).find('br').replaceWith(function () {
return document.createTextNode('\n');
});
$(block).find('p').replaceWith(function () {
return $(this).contents();
});
},
removeTagsInsidePre: function removeTagsInsidePre(html) {
var $div = $('
').append(html);
$div.find('pre').replaceWith(function () {
var str = $(this).html();
str = str.replace(/
|<\/p>|<\/div>|<\/li>|<\/td>/gi, '\n');
str = str.replace(/(<([^>]+)>)/gi, '');
return $('
').append(str);
});
html = $div.html();
$div.remove();
return html;
},
getPlainText: function getPlainText(html) {
html = html.replace(//gi, '');
html = html.replace(/