
META-INF.resources.bower_components.textAngular.src.factories.js Maven / Gradle / Ivy
angular.module('textAngular.factories', [])
.factory('taBrowserTag', [function () {
return function (tag) {
/* istanbul ignore next: ie specific test */
if (!tag) return (_browserDetect.ie <= 8) ? 'P' : 'p';
else if (tag === '') return (_browserDetect.ie === undefined) ? 'div' : (_browserDetect.ie <= 8) ? 'P' : 'p';
else return (_browserDetect.ie <= 8) ? tag.toUpperCase() : tag;
};
}]).factory('taApplyCustomRenderers', ['taCustomRenderers', 'taDOM', function (taCustomRenderers, taDOM) {
return function (val) {
var element = angular.element('');
element[0].innerHTML = val;
angular.forEach(taCustomRenderers, function (renderer) {
var elements = [];
// get elements based on what is defined. If both defined do secondary filter in the forEach after using selector string
if (renderer.selector && renderer.selector !== '')
elements = element.find(renderer.selector);
/* istanbul ignore else: shouldn't fire, if it does we're ignoring everything */
else if (renderer.customAttribute && renderer.customAttribute !== '')
elements = taDOM.getByAttribute(element, renderer.customAttribute);
// process elements if any found
angular.forEach(elements, function (_element) {
_element = angular.element(_element);
if (renderer.selector && renderer.selector !== '' && renderer.customAttribute && renderer.customAttribute !== '') {
if (_element.attr(renderer.customAttribute) !== undefined) renderer.renderLogic(_element);
} else renderer.renderLogic(_element);
});
});
return element[0].innerHTML;
};
}]).factory('taFixChrome', function () {
// get whaterever rubbish is inserted in chrome
// should be passed an html string, returns an html string
var taFixChrome = function (html, keepStyles) {
if (!html || !angular.isString(html) || html.length <= 0) return html;
// grab all elements with a style attibute
// a betterSpanMatch matches only a style=... with matching quotes
// this captures the whole:
// 'style="background-color: rgb(255, 255, 255);"'
var betterSpanMatch = /style\s?=\s?(["'])(?:(?=(\\?))\2.)*?\1/ig;
// where the original spanMatch = /<([^>\/]+?)style=("([^\"]+)"|'([^']+)')([^>]*)>/ig;
// captures too much and includes the front tag!
var spanMatch = /<([^>\/]+?)style=("([^\"]+)"|'([^']+)')([^>]*)>/ig;
var appleConvertedSpaceMatch = /([^<]+)<\/span>/ig;
var match, styleVal, appleSpaceVal, newTag, finalHtml = '', lastIndex = 0;
// remove all the Apple-converted-space spans and replace with the content of the span
//console.log('before:', html);
/* istanbul ignore next: apple-contereted-space span match */
while (match = appleConvertedSpaceMatch.exec(html)) {
appleSpaceVal = match[1];
appleSpaceVal = appleSpaceVal.replace(/ /ig, ' ');
finalHtml += html.substring(lastIndex, match.index) + appleSpaceVal;
lastIndex = match.index + match[0].length;
}
/* istanbul ignore next: apple-contereted-space span has matched */
if (lastIndex) {
// modified....
finalHtml += html.substring(lastIndex);
html = finalHtml;
finalHtml = '';
lastIndex = 0;
}
/////////////////////////////////////////////////////////////
//
// Allow control of this modification
// taKeepStyles: False - removes these modification
//
// taFixChrome removes the following styles:
// font-family: inherit;
// line-height:
// color: inherit;
// color: rgb( #{3} )
// background-color: rgb( #{3} )
//
/////////////////////////////////////////////////////////////
if (!keepStyles) {
while (match = betterSpanMatch.exec(html)) {
finalHtml += html.substring(lastIndex, match.index - 1);
styleVal = match[0];
// test for chrome inserted junk
match = /font-family: inherit;|line-height: 1.[0-9]{3,12};|color: inherit; line-height: 1.1;|color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);|background-color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);/gi.exec(styleVal);
if (match) {
styleVal = styleVal.replace(/( |)font-family: inherit;|( |)line-height: 1.[0-9]{3,12};|( |)color: inherit;|( |)color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);|( |)background-color: rgb\(\d{1,3}, \d{1,3}, \d{1,3}\);/ig, '');
//console.log(styleVal, styleVal.length);
if (styleVal.length > 8) {
finalHtml += ' ' + styleVal;
}
} else {
finalHtml += ' ' + styleVal;
}
lastIndex = betterSpanMatch.lastIndex;
}
finalHtml += html.substring(lastIndex);
}
//console.log('final:', finalHtml);
// only replace when something has changed, else we get focus problems on inserting lists
if (lastIndex > 0) {
// replace all empty strings
var fe = finalHtml.replace(/(.*?)<\/span>(
|)/ig, '$1');
return fe;
} else return html;
};
return taFixChrome;
}).factory('taSanitize', ['$sanitize', function taSanitizeFactory($sanitize) {
var convert_infos = [
{
property: 'font-weight',
values: ['bold'],
tag: 'b'
},
{
property: 'font-style',
values: ['italic'],
tag: 'i'
}
];
var styleMatch = [];
for (var i = 0; i < convert_infos.length; i++) {
var _partialStyle = '(' + convert_infos[i].property + ':\\s*(';
for (var j = 0; j < convert_infos[i].values.length; j++) {
/* istanbul ignore next: not needed to be tested yet */
if (j > 0) _partialStyle += '|';
_partialStyle += convert_infos[i].values[j];
}
_partialStyle += ');)';
styleMatch.push(_partialStyle);
}
var styleRegexString = '(' + styleMatch.join('|') + ')';
function wrapNested(html, wrapTag) {
var depth = 0;
var lastIndex = 0;
var match;
var tagRegex = /<[^>]*>/ig;
while (match = tagRegex.exec(html)) {
lastIndex = match.index;
if (match[0].substr(1, 1) === '/') {
if (depth === 0) break;
else depth--;
} else depth++;
}
return wrapTag +
html.substring(0, lastIndex) +
// get the start tags reversed - this is safe as we construct the strings with no content except the tags
angular.element(wrapTag)[0].outerHTML.substring(wrapTag.length) +
html.substring(lastIndex);
}
function transformLegacyStyles(html) {
if (!html || !angular.isString(html) || html.length <= 0) return html;
var i;
var styleElementMatch = /<([^>\/]+?)style=("([^"]+)"|'([^']+)')([^>]*)>/ig;
var match, subMatch, styleVal, newTag, lastNewTag = '', newHtml, finalHtml = '', lastIndex = 0;
while (match = styleElementMatch.exec(html)) {
// one of the quoted values ' or "
/* istanbul ignore next: quotations match */
styleVal = match[3] || match[4];
var styleRegex = new RegExp(styleRegexString, 'i');
// test for style values to change
if (angular.isString(styleVal) && styleRegex.test(styleVal)) {
// remove build tag list
newTag = '';
// init regex here for exec
var styleRegexExec = new RegExp(styleRegexString, 'ig');
// find relevand tags and build a string of them
while (subMatch = styleRegexExec.exec(styleVal)) {
for (i = 0; i < convert_infos.length; i++) {
if (!!subMatch[(i * 2) + 2]) {
newTag += '<' + convert_infos[i].tag + '>';
}
}
}
// recursively find more legacy styles in html before this tag and after the previous match (if any)
newHtml = transformLegacyStyles(html.substring(lastIndex, match.index));
// build up html
if (lastNewTag.length > 0) {
finalHtml += wrapNested(newHtml, lastNewTag);
} else finalHtml += newHtml;
// grab the style val without the transformed values
styleVal = styleVal.replace(new RegExp(styleRegexString, 'ig'), '');
// build the html tag
finalHtml += '<' + match[1].trim();
if (styleVal.length > 0) finalHtml += ' style="' + styleVal + '"';
finalHtml += match[5] + '>';
// update the start index to after this tag
lastIndex = match.index + match[0].length;
lastNewTag = newTag;
}
}
if (lastNewTag.length > 0) {
finalHtml += wrapNested(html.substring(lastIndex), lastNewTag);
}
else finalHtml += html.substring(lastIndex);
return finalHtml;
}
function transformLegacyAttributes(html) {
if (!html || !angular.isString(html) || html.length <= 0) return html;
// replace all align='...' tags with text-align attributes
var attrElementMatch = /<([^>\/]+?)align=("([^"]+)"|'([^']+)')([^>]*)>/ig;
var match, finalHtml = '', lastIndex = 0;
// match all attr tags
while (match = attrElementMatch.exec(html)) {
// add all html before this tag
finalHtml += html.substring(lastIndex, match.index);
// record last index after this tag
lastIndex = match.index + match[0].length;
// construct tag without the align attribute
var newTag = '<' + match[1] + match[5];
// add the style attribute
if (/style=("([^"]+)"|'([^']+)')/ig.test(newTag)) {
/* istanbul ignore next: quotations match */
newTag = newTag.replace(/style=("([^"]+)"|'([^']+)')/i, 'style="$2$3 text-align:' + (match[3] || match[4]) + ';"');
} else {
/* istanbul ignore next: quotations match */
newTag += ' style="text-align:' + (match[3] || match[4]) + ';"';
}
newTag += '>';
// add to html
finalHtml += newTag;
}
// return with remaining html
return finalHtml + html.substring(lastIndex);
}
// use precompiled regexp for speed
var rsb1 = new RegExp(/[^<>]+?<\/span>/ig);
var rsb2 = new RegExp(/[^<>]+?<\/span>/ig);
var rsb3 = new RegExp(/[^<>]+?<\/span>/ig);
return function taSanitize(unsafe, oldsafe, ignore) {
// unsafe html should NEVER built into a DOM object via angular.element. This allows XSS to be inserted and run.
if (!ignore) {
try {
unsafe = transformLegacyStyles(unsafe);
} catch (e) {
}
}
// unsafe and oldsafe should be valid HTML strings
// any exceptions (lets say, color for example) should be made here but with great care
// setup unsafe element for modification
unsafe = transformLegacyAttributes(unsafe);
// we had an issue in the past, where we dumped a whole bunch of 's into the content...
// so we remove them here
// IN A FUTURE release this can be removed after all have updated through release 1.5.9
if (unsafe) {
try {
unsafe = unsafe.replace(rsb1, '');
unsafe = unsafe.replace(rsb2, '');
unsafe = unsafe.replace(rsb1, '');
unsafe = unsafe.replace(rsb3, '');
} catch (e) {
}
}
var safe;
try {
safe = $sanitize(unsafe);
// do this afterwards, then the $sanitizer should still throw for bad markup
if (ignore) safe = unsafe;
} catch (e) {
safe = oldsafe || '';
}
// Do processing for tags, removing tabs and return carriages outside of them
var _preTags = safe.match(/(]*>.*?<\/pre[^>]*>)/ig);
var processedSafe = safe.replace(/((9|10);)*/ig, '');
var re = /]*>.*?<\/pre[^>]*>/ig;
var index = 0;
var lastIndex = 0;
var origTag;
safe = '';
while ((origTag = re.exec(processedSafe)) !== null && index < _preTags.length) {
safe += processedSafe.substring(lastIndex, origTag.index) + _preTags[index];
lastIndex = origTag.index + origTag[0].length;
index++;
}
return safe + processedSafe.substring(lastIndex);
};
}]).factory('taToolExecuteAction', ['$q', '$log', function ($q, $log) {
// this must be called on a toolScope or instance
return function (editor) {
if (editor !== undefined) this.$editor = function () {
return editor;
};
var deferred = $q.defer(),
promise = deferred.promise,
_editor = this.$editor();
// pass into the action the deferred function and also the function to reload the current selection if rangy available
var result;
try {
result = this.action(deferred, _editor.startAction());
// We set the .finally callback here to make sure it doesn't get executed before any other .then callback.
promise['finally'](function () {
_editor.endAction.call(_editor);
});
} catch (exc) {
$log.error(exc);
}
if (result || result === undefined) {
// if true or undefined is returned then the action has finished. Otherwise the deferred action will be resolved manually.
deferred.resolve();
}
};
}]);
© 2015 - 2025 Weber Informatics LLC | Privacy Policy