Merge branch 'MDL-47002-master' of git://github.com/merrill-oakland/moodle
This commit is contained in:
+131
-3
@@ -298,7 +298,8 @@ Y.extend(Editor, Y.Base, {
|
||||
* @chainable
|
||||
*/
|
||||
setupAutomaticPolling: function() {
|
||||
this._registerEventHandle(this.editor.on(['keyup', 'paste', 'cut'], this.updateOriginal, this));
|
||||
this._registerEventHandle(this.editor.on(['keyup', 'cut'], this.updateOriginal, this));
|
||||
this._registerEventHandle(this.editor.on('paste', this.pasteCleanup, this));
|
||||
|
||||
// Call this.updateOriginal after dropped content has been processed.
|
||||
this._registerEventHandle(this.editor.on('drop', this.updateOriginalDelayed, this));
|
||||
@@ -1129,10 +1130,12 @@ EditorClean.prototype = {
|
||||
{regex: /<span[^>]*>( |\s)*<\/span>/gi, replace: ""},
|
||||
// Remove class="Msoblah"
|
||||
{regex: /class="Mso[^"]*"/gi, replace: ""},
|
||||
// Remove any open HTML comment opens that are not followed by a close. This can completely break page layout.
|
||||
{regex: /<!--(?![\s\S]*?-->)/gi, replace: ""},
|
||||
|
||||
// Source: "http://www.codinghorror.com/blog/2006/01/cleaning-words-nasty-html.html"
|
||||
// Remove forbidden tags for content, title, meta, style, st0-9, head, font, html, body.
|
||||
{regex: /<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|!\[)[^>]*?>/gi, replace: ""},
|
||||
// Remove forbidden tags for content, title, meta, style, st0-9, head, font, html, body, link.
|
||||
{regex: /<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|\/?link|!\[)[^>]*?>/gi, replace: ""},
|
||||
|
||||
// Source: "http://www.tim-jarrett.com/labs_javascript_scrub_word.php"
|
||||
// Replace extended chars with simple text.
|
||||
@@ -1155,6 +1158,131 @@ EditorClean.prototype = {
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Intercept and clean html paste events.
|
||||
*
|
||||
* @method pasteCleanup
|
||||
* @param {Object} sourceEvent The YUI EventFacade object
|
||||
* @return {Boolean} True if the passed event should continue, false if not.
|
||||
*/
|
||||
pasteCleanup: function(sourceEvent) {
|
||||
// We only expect paste events, but we will check anyways.
|
||||
if (sourceEvent.type === 'paste') {
|
||||
// The YUI event wrapper doesn't provide paste event info, so we need the underlying event.
|
||||
var event = sourceEvent._event;
|
||||
// Check if we have a valid clipboardData object in the event.
|
||||
// IE has a clipboard object at window.clipboardData, but as of IE 11, it does not provide HTML content access.
|
||||
if (event && event.clipboardData && event.clipboardData.getData) {
|
||||
// Check if there is HTML type to be pasted, this is all we care about.
|
||||
var types = event.clipboardData.types;
|
||||
var isHTML = false;
|
||||
// Different browsers use different things to hold the types, so test various functions.
|
||||
if (!types) {
|
||||
isHTML = false;
|
||||
} else if (typeof types.contains === 'function') {
|
||||
isHTML = types.contains('text/html');
|
||||
} else if (typeof types.indexOf === 'function') {
|
||||
isHTML = (types.indexOf('text/html') > -1);
|
||||
if (!isHTML) {
|
||||
if ((types.indexOf('com.apple.webarchive') > -1) || (types.indexOf('com.apple.iWork.TSPNativeData') > -1)) {
|
||||
// This is going to be a specialized Apple paste paste. We cannot capture this, so clean everything.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We don't know how to handle the clipboard info, so wait for the clipboard event to finish then fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isHTML) {
|
||||
// Get the clipboard content.
|
||||
var content;
|
||||
try {
|
||||
content = event.clipboardData.getData('text/html');
|
||||
} catch (error) {
|
||||
// Something went wrong. Fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stop the original paste.
|
||||
sourceEvent.preventDefault();
|
||||
|
||||
// Scrub the paste content.
|
||||
content = this._cleanHTML(content);
|
||||
|
||||
// Save the current selection.
|
||||
// Using saveSelection as it produces a more consistent experience.
|
||||
var selection = window.rangy.saveSelection();
|
||||
|
||||
// Insert the content.
|
||||
this.insertContentAtFocusPoint(content);
|
||||
|
||||
// Restore the selection, and collapse to end.
|
||||
window.rangy.restoreSelection(selection);
|
||||
window.rangy.getSelection().collapseToEnd();
|
||||
|
||||
// Update the text area.
|
||||
this.updateOriginal();
|
||||
return false;
|
||||
} else {
|
||||
// This is a non-html paste event, we can just let this continue on and call updateOriginalDelayed.
|
||||
this.updateOriginalDelayed();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// If we reached a here, this probably means the browser has limited (or no) clipboard support.
|
||||
// Wait for the clipboard event to finish then fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We should never get here - we must have received a non-paste event for some reason.
|
||||
// Um, just call updateOriginalDelayed() - it's safe.
|
||||
this.updateOriginalDelayed();
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cleanup code after a paste event if we couldn't intercept the paste content.
|
||||
*
|
||||
* @method fallbackPasteCleanup
|
||||
* @chainable
|
||||
*/
|
||||
fallbackPasteCleanup: function() {
|
||||
Y.log('Using fallbackPasteCleanup for atto cleanup', 'debug', LOGNAME);
|
||||
|
||||
// Save the current selection (cursor position).
|
||||
var selection = window.rangy.saveSelection();
|
||||
|
||||
// Get, clean, and replace the content in the editable.
|
||||
var content = this.editor.get('innerHTML');
|
||||
this.editor.set('innerHTML', this._cleanHTML(content));
|
||||
|
||||
// Update the textarea.
|
||||
this.updateOriginal();
|
||||
|
||||
// Restore the selection (cursor position).
|
||||
window.rangy.restoreSelection(selection);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calls fallbackPasteCleanup on a short timer to allow the paste event handlers to complete.
|
||||
*
|
||||
* @method fallbackPasteCleanupDelayed
|
||||
* @chainable
|
||||
*/
|
||||
fallbackPasteCleanupDelayed: function() {
|
||||
Y.soon(Y.bind(this.fallbackPasteCleanup, this));
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+4
-3
File diff suppressed because one or more lines are too long
+130
-3
@@ -296,7 +296,8 @@ Y.extend(Editor, Y.Base, {
|
||||
* @chainable
|
||||
*/
|
||||
setupAutomaticPolling: function() {
|
||||
this._registerEventHandle(this.editor.on(['keyup', 'paste', 'cut'], this.updateOriginal, this));
|
||||
this._registerEventHandle(this.editor.on(['keyup', 'cut'], this.updateOriginal, this));
|
||||
this._registerEventHandle(this.editor.on('paste', this.pasteCleanup, this));
|
||||
|
||||
// Call this.updateOriginal after dropped content has been processed.
|
||||
this._registerEventHandle(this.editor.on('drop', this.updateOriginalDelayed, this));
|
||||
@@ -1119,10 +1120,12 @@ EditorClean.prototype = {
|
||||
{regex: /<span[^>]*>( |\s)*<\/span>/gi, replace: ""},
|
||||
// Remove class="Msoblah"
|
||||
{regex: /class="Mso[^"]*"/gi, replace: ""},
|
||||
// Remove any open HTML comment opens that are not followed by a close. This can completely break page layout.
|
||||
{regex: /<!--(?![\s\S]*?-->)/gi, replace: ""},
|
||||
|
||||
// Source: "http://www.codinghorror.com/blog/2006/01/cleaning-words-nasty-html.html"
|
||||
// Remove forbidden tags for content, title, meta, style, st0-9, head, font, html, body.
|
||||
{regex: /<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|!\[)[^>]*?>/gi, replace: ""},
|
||||
// Remove forbidden tags for content, title, meta, style, st0-9, head, font, html, body, link.
|
||||
{regex: /<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|\/?link|!\[)[^>]*?>/gi, replace: ""},
|
||||
|
||||
// Source: "http://www.tim-jarrett.com/labs_javascript_scrub_word.php"
|
||||
// Replace extended chars with simple text.
|
||||
@@ -1145,6 +1148,130 @@ EditorClean.prototype = {
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Intercept and clean html paste events.
|
||||
*
|
||||
* @method pasteCleanup
|
||||
* @param {Object} sourceEvent The YUI EventFacade object
|
||||
* @return {Boolean} True if the passed event should continue, false if not.
|
||||
*/
|
||||
pasteCleanup: function(sourceEvent) {
|
||||
// We only expect paste events, but we will check anyways.
|
||||
if (sourceEvent.type === 'paste') {
|
||||
// The YUI event wrapper doesn't provide paste event info, so we need the underlying event.
|
||||
var event = sourceEvent._event;
|
||||
// Check if we have a valid clipboardData object in the event.
|
||||
// IE has a clipboard object at window.clipboardData, but as of IE 11, it does not provide HTML content access.
|
||||
if (event && event.clipboardData && event.clipboardData.getData) {
|
||||
// Check if there is HTML type to be pasted, this is all we care about.
|
||||
var types = event.clipboardData.types;
|
||||
var isHTML = false;
|
||||
// Different browsers use different things to hold the types, so test various functions.
|
||||
if (!types) {
|
||||
isHTML = false;
|
||||
} else if (typeof types.contains === 'function') {
|
||||
isHTML = types.contains('text/html');
|
||||
} else if (typeof types.indexOf === 'function') {
|
||||
isHTML = (types.indexOf('text/html') > -1);
|
||||
if (!isHTML) {
|
||||
if ((types.indexOf('com.apple.webarchive') > -1) || (types.indexOf('com.apple.iWork.TSPNativeData') > -1)) {
|
||||
// This is going to be a specialized Apple paste paste. We cannot capture this, so clean everything.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We don't know how to handle the clipboard info, so wait for the clipboard event to finish then fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isHTML) {
|
||||
// Get the clipboard content.
|
||||
var content;
|
||||
try {
|
||||
content = event.clipboardData.getData('text/html');
|
||||
} catch (error) {
|
||||
// Something went wrong. Fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stop the original paste.
|
||||
sourceEvent.preventDefault();
|
||||
|
||||
// Scrub the paste content.
|
||||
content = this._cleanHTML(content);
|
||||
|
||||
// Save the current selection.
|
||||
// Using saveSelection as it produces a more consistent experience.
|
||||
var selection = window.rangy.saveSelection();
|
||||
|
||||
// Insert the content.
|
||||
this.insertContentAtFocusPoint(content);
|
||||
|
||||
// Restore the selection, and collapse to end.
|
||||
window.rangy.restoreSelection(selection);
|
||||
window.rangy.getSelection().collapseToEnd();
|
||||
|
||||
// Update the text area.
|
||||
this.updateOriginal();
|
||||
return false;
|
||||
} else {
|
||||
// This is a non-html paste event, we can just let this continue on and call updateOriginalDelayed.
|
||||
this.updateOriginalDelayed();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// If we reached a here, this probably means the browser has limited (or no) clipboard support.
|
||||
// Wait for the clipboard event to finish then fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We should never get here - we must have received a non-paste event for some reason.
|
||||
// Um, just call updateOriginalDelayed() - it's safe.
|
||||
this.updateOriginalDelayed();
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cleanup code after a paste event if we couldn't intercept the paste content.
|
||||
*
|
||||
* @method fallbackPasteCleanup
|
||||
* @chainable
|
||||
*/
|
||||
fallbackPasteCleanup: function() {
|
||||
|
||||
// Save the current selection (cursor position).
|
||||
var selection = window.rangy.saveSelection();
|
||||
|
||||
// Get, clean, and replace the content in the editable.
|
||||
var content = this.editor.get('innerHTML');
|
||||
this.editor.set('innerHTML', this._cleanHTML(content));
|
||||
|
||||
// Update the textarea.
|
||||
this.updateOriginal();
|
||||
|
||||
// Restore the selection (cursor position).
|
||||
window.rangy.restoreSelection(selection);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calls fallbackPasteCleanup on a short timer to allow the paste event handlers to complete.
|
||||
*
|
||||
* @method fallbackPasteCleanupDelayed
|
||||
* @chainable
|
||||
*/
|
||||
fallbackPasteCleanupDelayed: function() {
|
||||
Y.soon(Y.bind(this.fallbackPasteCleanup, this));
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+129
-2
@@ -105,10 +105,12 @@ EditorClean.prototype = {
|
||||
{regex: /<span[^>]*>( |\s)*<\/span>/gi, replace: ""},
|
||||
// Remove class="Msoblah"
|
||||
{regex: /class="Mso[^"]*"/gi, replace: ""},
|
||||
// Remove any open HTML comment opens that are not followed by a close. This can completely break page layout.
|
||||
{regex: /<!--(?![\s\S]*?-->)/gi, replace: ""},
|
||||
|
||||
// Source: "http://www.codinghorror.com/blog/2006/01/cleaning-words-nasty-html.html"
|
||||
// Remove forbidden tags for content, title, meta, style, st0-9, head, font, html, body.
|
||||
{regex: /<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|!\[)[^>]*?>/gi, replace: ""},
|
||||
// Remove forbidden tags for content, title, meta, style, st0-9, head, font, html, body, link.
|
||||
{regex: /<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|\/?link|!\[)[^>]*?>/gi, replace: ""},
|
||||
|
||||
// Source: "http://www.tim-jarrett.com/labs_javascript_scrub_word.php"
|
||||
// Replace extended chars with simple text.
|
||||
@@ -131,6 +133,131 @@ EditorClean.prototype = {
|
||||
}
|
||||
|
||||
return content;
|
||||
},
|
||||
|
||||
/**
|
||||
* Intercept and clean html paste events.
|
||||
*
|
||||
* @method pasteCleanup
|
||||
* @param {Object} sourceEvent The YUI EventFacade object
|
||||
* @return {Boolean} True if the passed event should continue, false if not.
|
||||
*/
|
||||
pasteCleanup: function(sourceEvent) {
|
||||
// We only expect paste events, but we will check anyways.
|
||||
if (sourceEvent.type === 'paste') {
|
||||
// The YUI event wrapper doesn't provide paste event info, so we need the underlying event.
|
||||
var event = sourceEvent._event;
|
||||
// Check if we have a valid clipboardData object in the event.
|
||||
// IE has a clipboard object at window.clipboardData, but as of IE 11, it does not provide HTML content access.
|
||||
if (event && event.clipboardData && event.clipboardData.getData) {
|
||||
// Check if there is HTML type to be pasted, this is all we care about.
|
||||
var types = event.clipboardData.types;
|
||||
var isHTML = false;
|
||||
// Different browsers use different things to hold the types, so test various functions.
|
||||
if (!types) {
|
||||
isHTML = false;
|
||||
} else if (typeof types.contains === 'function') {
|
||||
isHTML = types.contains('text/html');
|
||||
} else if (typeof types.indexOf === 'function') {
|
||||
isHTML = (types.indexOf('text/html') > -1);
|
||||
if (!isHTML) {
|
||||
if ((types.indexOf('com.apple.webarchive') > -1) || (types.indexOf('com.apple.iWork.TSPNativeData') > -1)) {
|
||||
// This is going to be a specialized Apple paste paste. We cannot capture this, so clean everything.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We don't know how to handle the clipboard info, so wait for the clipboard event to finish then fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isHTML) {
|
||||
// Get the clipboard content.
|
||||
var content;
|
||||
try {
|
||||
content = event.clipboardData.getData('text/html');
|
||||
} catch (error) {
|
||||
// Something went wrong. Fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Stop the original paste.
|
||||
sourceEvent.preventDefault();
|
||||
|
||||
// Scrub the paste content.
|
||||
content = this._cleanHTML(content);
|
||||
|
||||
// Save the current selection.
|
||||
// Using saveSelection as it produces a more consistent experience.
|
||||
var selection = window.rangy.saveSelection();
|
||||
|
||||
// Insert the content.
|
||||
this.insertContentAtFocusPoint(content);
|
||||
|
||||
// Restore the selection, and collapse to end.
|
||||
window.rangy.restoreSelection(selection);
|
||||
window.rangy.getSelection().collapseToEnd();
|
||||
|
||||
// Update the text area.
|
||||
this.updateOriginal();
|
||||
return false;
|
||||
} else {
|
||||
// This is a non-html paste event, we can just let this continue on and call updateOriginalDelayed.
|
||||
this.updateOriginalDelayed();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// If we reached a here, this probably means the browser has limited (or no) clipboard support.
|
||||
// Wait for the clipboard event to finish then fallback.
|
||||
this.fallbackPasteCleanupDelayed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// We should never get here - we must have received a non-paste event for some reason.
|
||||
// Um, just call updateOriginalDelayed() - it's safe.
|
||||
this.updateOriginalDelayed();
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Cleanup code after a paste event if we couldn't intercept the paste content.
|
||||
*
|
||||
* @method fallbackPasteCleanup
|
||||
* @chainable
|
||||
*/
|
||||
fallbackPasteCleanup: function() {
|
||||
Y.log('Using fallbackPasteCleanup for atto cleanup', 'debug', LOGNAME);
|
||||
|
||||
// Save the current selection (cursor position).
|
||||
var selection = window.rangy.saveSelection();
|
||||
|
||||
// Get, clean, and replace the content in the editable.
|
||||
var content = this.editor.get('innerHTML');
|
||||
this.editor.set('innerHTML', this._cleanHTML(content));
|
||||
|
||||
// Update the textarea.
|
||||
this.updateOriginal();
|
||||
|
||||
// Restore the selection (cursor position).
|
||||
window.rangy.restoreSelection(selection);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calls fallbackPasteCleanup on a short timer to allow the paste event handlers to complete.
|
||||
*
|
||||
* @method fallbackPasteCleanupDelayed
|
||||
* @chainable
|
||||
*/
|
||||
fallbackPasteCleanupDelayed: function() {
|
||||
Y.soon(Y.bind(this.fallbackPasteCleanup, this));
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-1
@@ -296,7 +296,8 @@ Y.extend(Editor, Y.Base, {
|
||||
* @chainable
|
||||
*/
|
||||
setupAutomaticPolling: function() {
|
||||
this._registerEventHandle(this.editor.on(['keyup', 'paste', 'cut'], this.updateOriginal, this));
|
||||
this._registerEventHandle(this.editor.on(['keyup', 'cut'], this.updateOriginal, this));
|
||||
this._registerEventHandle(this.editor.on('paste', this.pasteCleanup, this));
|
||||
|
||||
// Call this.updateOriginal after dropped content has been processed.
|
||||
this._registerEventHandle(this.editor.on('drop', this.updateOriginalDelayed, this));
|
||||
|
||||
Reference in New Issue
Block a user