Преглед на файлове

Merge pull request #6384 from ckeditor/i/6324

Added a warning notification in demo pages when user tries to paste content from MS Word or Google Docs. Closes #6324.
Marek Lewandowski преди 5 години
родител
ревизия
572f47af31
променени са 2 файла, в които са добавени 176 реда и са изтрити 1 реда
  1. 72 0
      docs/assets/snippet-styles.css
  2. 104 1
      docs/assets/snippet.js

+ 72 - 0
docs/assets/snippet-styles.css

@@ -109,6 +109,78 @@ It breaks CKEditor 5 (see how <p><code>[]</code></p> looks). */
 	margin-bottom: 0;
 }
 
+/* warning notification */
+
+.main__notification.notice {
+	position: fixed;
+	max-width: 650px;
+	border: 1px solid #e4e4e4;
+	border-left-color: #f9c669;
+	border-left-width: 3px;
+	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
+	/* override .notice class' margins and paddings */
+	padding: 20px 40px 20px 20px;
+	margin: 0;
+	/* elevate the warning above the editor's toolbars */
+	z-index: 99999999;
+	animation: fadeIn .3s ease-in-out forwards;
+}
+
+/* class chaining for style overriding */
+.formatted .main__notification-title {
+	font-weight: bold;
+	font-size: 16px;
+	padding: 0;
+	margin: 0;
+}
+
+.main__notification-body {
+	margin-top: 10px;
+}
+
+.main__notification-body p {
+  margin-bottom: 0.3em;
+}
+
+.main__notification-body p:last-child {
+	margin-bottom: 0;
+}
+
+.main__notification-close {
+	position: absolute;
+	top: 0;
+	right: 0;
+	padding: 10px;
+	/* reset default button styling */
+	background: none;
+	border: none;
+	box-shadow: none;
+	line-height: 1;
+	transition: background 150ms ease;
+	-webkit-appearance: none;
+	-moz-appearance: none;
+	appearance: none;
+	cursor: pointer;
+}
+
+.main__notification-close:hover {
+	background: #eee;
+}
+
+.main__notification-close:active:focus {
+	outline: none;
+}
+
+@keyframes fadeIn {
+	from {
+		opacity: 0;
+	}
+
+	to {
+		opacity: 1;
+	}
+}
+
 /* examples/builds/inline-editor.html */
 .live-snippet .image-style-left, .live-snippet .image-style-right {
 	float: left;

+ 104 - 1
docs/assets/snippet.js

@@ -3,7 +3,110 @@
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  */
 
-/* globals window, document */
+/* globals window, document, setTimeout */
+
+// Show clipboard input notification when user tries to paste a content from MS Word or Google Docs.
+setTimeout( () => {
+	// Don't show the warning notification in "Paste from Office" and "Paste from Google Docs" demos.
+	if ( window.preventPasteFromOfficeNotification ) {
+		return;
+	}
+
+	const editables = document.querySelectorAll( '.ck-content' );
+	const googleDocsMatch = /id=("|')docs-internal-guid-[-0-9a-f]+("|')/i;
+	const msWordMatch1 = /<meta\s*name="?generator"?\s*content="?microsoft\s*word\s*\d+"?\/?>/i;
+	const msWordMatch2 = /xmlns:o="urn:schemas-microsoft-com/i;
+
+	// A state variable that indicates if the clipboard notification has been seen.
+	// We use the variable for displaying the notification only once per demo.
+	let hasNotificationBeenSeen = false;
+
+	editables.forEach( editable => {
+		const editor = editable.ckeditorInstance;
+
+		if ( !editor ) {
+			return;
+		}
+
+		editor.plugins.get( 'Clipboard' ).listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {
+			const htmlString = data.dataTransfer.getData( 'text/html' );
+			const match = msWordMatch1.test( htmlString ) ||
+				msWordMatch2.test( htmlString ) ||
+				googleDocsMatch.test( htmlString );
+
+			if ( match && !hasNotificationBeenSeen ) {
+				createClipboardInputNotification();
+				hasNotificationBeenSeen = true;
+			}
+		} );
+	} );
+}, 3000 );
+
+// The notification should contain the links to the demos where user can test rich formatting from.
+function createClipboardInputNotification() {
+	const title = 'Hello!';
+	const message = `
+
+	<p>We detected that you tried to paste content from <strong>Microsoft Word</strong> or <strong>Google Docs</strong>.</p>
+	<p>Please bear in mind that the editor demo to which you try to paste does not have all the features enabled.
+		Due to that, unsupported formatting is being stripped.</p>
+	<p>Check out the <a href="/docs/ckeditor5/latest/features/pasting/paste-from-word.html">Paste from Word</a> or
+	<a href="/docs/ckeditor5/latest/pasting/paste-from-google-docs.html">Paste from Google Docs</a>
+	demos for the best experience.</p>`;
+
+	window.createNotification( title, message );
+}
+
+/**
+* Creates a notification and appends it to the `.main__content` element.
+*
+* @param {String} title A title of the notification.
+* @param {String} message A message to display in the notification.
+*
+* @returns {Object} A notification element.
+*/
+window.createNotification = function( title, message ) {
+	const notificationTemplate = `
+		<h3 class="main__notification-title">${ title }</h3>
+		<div class="main__notification-body">
+			${ message }
+		</div>
+	`;
+
+	const notification = document.createElement( 'div' );
+	const close = document.createElement( 'button' );
+
+	close.classList.add( 'main__notification-close' );
+	close.innerText = '✕';
+	close.setAttribute( 'aria-label', 'Close the notification' );
+
+	notification.classList.add( 'main__notification', 'notice' );
+	notification.innerHTML = notificationTemplate;
+	// ATM we support only top-right position.
+	notification.style.top = window.getViewportTopOffsetConfig() + 10 + 'px';
+	notification.style.right = '10px';
+	notification.appendChild( close );
+
+	const activeNotifications = document.querySelectorAll( '.main__notification' );
+
+	// Translate the position of multiple notifications (just in case).
+	if ( activeNotifications.length > 0 ) {
+		const moveOffset = activeNotifications.length * 10;
+
+		notification.style.top = parseInt( notification.style.top ) + moveOffset + 'px';
+		notification.style.right = parseInt( notification.style.right ) + moveOffset + 'px';
+	}
+
+	// Append notification to the `.main__content` element.
+	const main = document.querySelector( '.main__content' );
+	main.appendChild( notification );
+
+	close.addEventListener( 'click', () => {
+		main.removeChild( notification );
+	} );
+
+	return notification;
+};
 
 /**
  * Returns the `config.toolbar.viewportTopOffset` config value for editors using floating toolbars that