mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 04:51:31 +08:00 
			
		
		
		
	chore(ckeditor5/plugins): add file-upload
Original commit: a440988df452ab4367f5288269ba3c05aa5e6b8e
This commit is contained in:
		
							parent
							
								
									68456f0488
								
							
						
					
					
						commit
						26c060bd22
					
				
							
								
								
									
										18
									
								
								_regroup/ckeditor5-file-upload/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								_regroup/ckeditor5-file-upload/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | { | ||||||
|  |   "name": "@ckeditor/ckeditor5-file-upload", | ||||||
|  |   "version": "1.0.0", | ||||||
|  |   "description": "File Upload for CKEditor5", | ||||||
|  |   "main": "src/fileupload.js", | ||||||
|  |   "keywords": [ "ckeditor5" ], | ||||||
|  |   "dependencies": { | ||||||
|  |     "@ckeditor/ckeditor5-core": "^38.0.1", | ||||||
|  |     "@ckeditor/ckeditor5-upload": "^38.0.1", | ||||||
|  |     "@ckeditor/ckeditor5-ui": "^38.0.1", | ||||||
|  |     "@ckeditor/ckeditor5-clipboard": "^38.0.1", | ||||||
|  |     "@ckeditor/ckeditor5-engine": "^38.0.1", | ||||||
|  |     "@ckeditor/ckeditor5-utils": "^38.0.1", | ||||||
|  |     "@ckeditor/ckeditor5-widget": "^38.0.1" | ||||||
|  |   }, | ||||||
|  |   "license": "GPL-3.0", | ||||||
|  |   "devDependencies": {} | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								_regroup/ckeditor5-file-upload/src/fileuploadcommand.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								_regroup/ckeditor5-file-upload/src/fileuploadcommand.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | import { FileRepository } from 'ckeditor5/src/upload'; | ||||||
|  | import { Command } from 'ckeditor5/src/core'; | ||||||
|  | 
 | ||||||
|  | export default class FileUploadCommand extends Command { | ||||||
|  | 	refresh() { | ||||||
|  | 		this.isEnabled = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Executes the command. | ||||||
|  | 	 * | ||||||
|  | 	 * @fires execute | ||||||
|  | 	 * @param {Object} options Options for the executed command. | ||||||
|  | 	 * @param {File|Array.<File>} options.file The file or an array of files to upload. | ||||||
|  | 	 */ | ||||||
|  | 	execute( options ) { | ||||||
|  | 		const editor = this.editor; | ||||||
|  | 		const model = editor.model; | ||||||
|  | 
 | ||||||
|  | 		const fileRepository = editor.plugins.get( FileRepository ); | ||||||
|  | 
 | ||||||
|  | 		model.change( writer => { | ||||||
|  | 			const filesToUpload = options.file; | ||||||
|  | 			for ( const file of filesToUpload ) { | ||||||
|  | 				uploadFile( writer, model, fileRepository, file ); | ||||||
|  | 			} | ||||||
|  | 		} ); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 	Handles uploading single file. | ||||||
|  |  * | ||||||
|  |  *	@param {module:engine/model/writer~writer} writer | ||||||
|  |  *	@param {module:engine/model/model~Model} model | ||||||
|  |  *	@param {File} file | ||||||
|  |  */ | ||||||
|  | function uploadFile( writer, model, fileRepository, file ) { | ||||||
|  | 	const loader = fileRepository.createLoader( file ); | ||||||
|  | 
 | ||||||
|  | 	// Do not throw when upload adapter is not set. FileRepository will log an error anyway.
 | ||||||
|  | 	if ( !loader ) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	insertFileLink( writer, model, { href: '', uploadId: loader.id }, file ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function insertFileLink( writer, model, attributes = {}, file ) { | ||||||
|  | 	const placeholder = writer.createElement( 'reference', attributes ); | ||||||
|  | 	model.insertContent( placeholder, model.document.selection ); | ||||||
|  | 	writer.insertText( ' ', placeholder, 'after' ); | ||||||
|  | } | ||||||
							
								
								
									
										261
									
								
								_regroup/ckeditor5-file-upload/src/fileuploadediting.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								_regroup/ckeditor5-file-upload/src/fileuploadediting.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,261 @@ | |||||||
|  | import { Plugin } from 'ckeditor5/src/core'; | ||||||
|  | import { FileRepository } from 'ckeditor5/src/upload'; | ||||||
|  | import { Notification } from 'ckeditor5/src/ui'; | ||||||
|  | import { Clipboard } from 'ckeditor5/src/clipboard'; | ||||||
|  | import { UpcastWriter } from 'ckeditor5/src/engine'; | ||||||
|  | 
 | ||||||
|  | import FileUploadCommand from './fileuploadcommand'; | ||||||
|  | 
 | ||||||
|  | export default class FileUploadEditing extends Plugin { | ||||||
|  | 	static get requires() { | ||||||
|  | 		return [ FileRepository, Notification, Clipboard ]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	static get pluginName() { | ||||||
|  | 		return 'FileUploadEditing'; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	init() { | ||||||
|  | 		const editor = this.editor; | ||||||
|  | 		const doc = editor.model.document; | ||||||
|  | 		const conversion = editor.conversion; | ||||||
|  | 		const fileRepository = editor.plugins.get( FileRepository ); | ||||||
|  | 
 | ||||||
|  | 		// Register fileUpload command.
 | ||||||
|  | 		editor.commands.add( 'fileUpload', new FileUploadCommand( editor ) ); | ||||||
|  | 
 | ||||||
|  | 		// Register upcast converter for uploadId.
 | ||||||
|  | 		conversion.for( 'upcast' ) | ||||||
|  | 			.attributeToAttribute( { | ||||||
|  | 				view: { | ||||||
|  | 					name: 'a', | ||||||
|  | 					key: 'uploadId' | ||||||
|  | 				}, | ||||||
|  | 				model: 'uploadId' | ||||||
|  | 			} ); | ||||||
|  | 
 | ||||||
|  | 		this.listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => { | ||||||
|  | 			// Skip if non-empty HTML data is included.
 | ||||||
|  | 			// https://github.com/ckeditor/ckeditor5-upload/issues/68
 | ||||||
|  | 			if ( isHtmlIncluded( data.dataTransfer ) ) { | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			const files = Array.from( data.dataTransfer.files ); | ||||||
|  | 
 | ||||||
|  | 			editor.model.change( writer => { | ||||||
|  | 				// Set selection to paste target.
 | ||||||
|  | 				if ( data.targetRanges ) { | ||||||
|  | 					writer.setSelection( data.targetRanges.map( viewRange => editor.editing.mapper.toModelRange( viewRange ) ) ); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if ( files.length ) { | ||||||
|  | 					evt.stop(); | ||||||
|  | 
 | ||||||
|  | 					// Upload files after the selection has changed in order to ensure the command's state is refreshed.
 | ||||||
|  | 					editor.model.enqueueChange( 'default', () => { | ||||||
|  | 						editor.execute( 'fileUpload', { file: files } ); | ||||||
|  | 					} ); | ||||||
|  | 				} | ||||||
|  | 			} ); | ||||||
|  | 		} ); | ||||||
|  | 
 | ||||||
|  | 		this.listenTo( editor.plugins.get( Clipboard ), 'inputTransformation', ( evt, data ) => { | ||||||
|  | 			const fetchableFiles = Array.from( editor.editing.view.createRangeIn( data.content ) ) | ||||||
|  | 				.filter( value => isLocalFile( value.item ) && !value.item.getAttribute( 'uploadProcessed' ) ) | ||||||
|  | 				.map( value => { | ||||||
|  | 					return { promise: fetchLocalFile( value.item ), fileElement: value.item }; | ||||||
|  | 				} ); | ||||||
|  | 
 | ||||||
|  | 			if ( !fetchableFiles.length ) { | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			const writer = new UpcastWriter(); | ||||||
|  | 
 | ||||||
|  | 			for ( const fetchableFile of fetchableFiles ) { | ||||||
|  | 				// Set attribute marking that the file was processed already.
 | ||||||
|  | 				writer.setAttribute( 'uploadProcessed', true, fetchableFile.fileElement ); | ||||||
|  | 
 | ||||||
|  | 				const loader = fileRepository.createLoader( fetchableFile.promise ); | ||||||
|  | 
 | ||||||
|  | 				if ( loader ) { | ||||||
|  | 					writer.setAttribute( 'href', '', fetchableFile.fileElement ); | ||||||
|  | 					writer.setAttribute( 'uploadId', loader.id, fetchableFile.fileElement ); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} ); | ||||||
|  | 
 | ||||||
|  | 		// Prevents from the browser redirecting to the dropped file.
 | ||||||
|  | 		editor.editing.view.document.on( 'dragover', ( evt, data ) => { | ||||||
|  | 			data.preventDefault(); | ||||||
|  | 		} ); | ||||||
|  | 
 | ||||||
|  | 		// Upload placeholder files that appeared in the model.
 | ||||||
|  | 		doc.on( 'change', () => { | ||||||
|  | 			const changes = doc.differ.getChanges( { includeChangesInGraveyard: true } ); | ||||||
|  | 			for ( const entry of changes ) { | ||||||
|  | 				if ( entry.type == 'insert' ) { | ||||||
|  | 					const item = entry.position.nodeAfter; | ||||||
|  | 					if ( item ) { | ||||||
|  | 						const isInGraveyard = entry.position.root.rootName == '$graveyard'; | ||||||
|  | 						for ( const file of getFileLinksFromChangeItem( editor, item ) ) { | ||||||
|  | 							// Check if the file element still has upload id.
 | ||||||
|  | 							const uploadId = file.getAttribute( 'uploadId' ); | ||||||
|  | 							if ( !uploadId ) { | ||||||
|  | 								continue; | ||||||
|  | 							} | ||||||
|  | 
 | ||||||
|  | 							// Check if the file is loaded on this client.
 | ||||||
|  | 							const loader = fileRepository.loaders.get( uploadId ); | ||||||
|  | 
 | ||||||
|  | 							if ( !loader ) { | ||||||
|  | 								continue; | ||||||
|  | 							} | ||||||
|  | 
 | ||||||
|  | 							if ( isInGraveyard ) { | ||||||
|  | 								// If the file was inserted to the graveyard - abort the loading process.
 | ||||||
|  | 								loader.abort(); | ||||||
|  | 							} else if ( loader.status == 'idle' ) { | ||||||
|  | 								// If the file was inserted into content and has not been loaded yet, start loading it.
 | ||||||
|  | 								this._readAndUpload( loader, file ); | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_readAndUpload( loader, fileElement ) { | ||||||
|  | 		const editor = this.editor; | ||||||
|  | 		const model = editor.model; | ||||||
|  | 		const t = editor.locale.t; | ||||||
|  | 		const fileRepository = editor.plugins.get( FileRepository ); | ||||||
|  | 		const notification = editor.plugins.get( Notification ); | ||||||
|  | 
 | ||||||
|  | 		model.enqueueChange( 'transparent', writer => { | ||||||
|  | 			writer.setAttribute( 'uploadStatus', 'reading', fileElement ); | ||||||
|  | 		} ); | ||||||
|  | 
 | ||||||
|  | 		return loader.read() | ||||||
|  | 			.then( () => { | ||||||
|  | 				const promise = loader.upload(); | ||||||
|  | 
 | ||||||
|  | 				model.enqueueChange( 'transparent', writer => { | ||||||
|  | 					writer.setAttribute( 'uploadStatus', 'uploading', fileElement ); | ||||||
|  | 				} ); | ||||||
|  | 
 | ||||||
|  | 				return promise; | ||||||
|  | 			} ) | ||||||
|  | 			.then( data => { | ||||||
|  | 				model.enqueueChange( 'transparent', writer => { | ||||||
|  | 					writer.setAttributes( { uploadStatus: 'complete', href: data.default }, fileElement ); | ||||||
|  | 				} ); | ||||||
|  | 
 | ||||||
|  | 				clean(); | ||||||
|  | 
 | ||||||
|  | 				// wait a bit so that froca has time to load the changes
 | ||||||
|  | 				return new Promise(res => setTimeout(res, 100)); | ||||||
|  | 			} ) | ||||||
|  | 			.then(() => { | ||||||
|  | 				// we're correctly updating the model, but the view remains broken,
 | ||||||
|  | 				// hack around it is to force CKEditor to reload the now updated HTML
 | ||||||
|  | 				editor.setData(editor.getData()); | ||||||
|  | 			}) | ||||||
|  | 			.catch( error => { | ||||||
|  | 				// If status is not 'error' nor 'aborted' - throw error, because it means that something else went wrong,
 | ||||||
|  | 				// it might be a generic error, and it would be real pain to find what is going on.
 | ||||||
|  | 				if ( loader.status !== 'error' && loader.status !== 'aborted' ) { | ||||||
|  | 					throw error; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// Might be 'aborted'.
 | ||||||
|  | 				if ( loader.status == 'error' && error ) { | ||||||
|  | 					notification.showWarning( error, { | ||||||
|  | 						title: t( 'Upload failed' ), | ||||||
|  | 						namespace: 'upload' | ||||||
|  | 					} ); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				clean(); | ||||||
|  | 
 | ||||||
|  | 				// Permanently remove file from insertion batch.
 | ||||||
|  | 				model.enqueueChange( 'transparent', writer => { | ||||||
|  | 					writer.remove( fileElement ); | ||||||
|  | 				} ); | ||||||
|  | 			} ); | ||||||
|  | 
 | ||||||
|  | 		function clean() { | ||||||
|  | 			model.enqueueChange( 'transparent', writer => { | ||||||
|  | 				writer.removeAttribute( 'uploadId', fileElement ); | ||||||
|  | 				writer.removeAttribute( 'uploadStatus', fileElement ); | ||||||
|  | 			} ); | ||||||
|  | 
 | ||||||
|  | 			fileRepository.destroyLoader( loader ); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function fetchLocalFile( link ) { | ||||||
|  | 	return new Promise( ( resolve, reject ) => { | ||||||
|  | 		const href = link.getAttribute( 'href' ); | ||||||
|  | 
 | ||||||
|  | 		// Fetch works asynchronously and so does not block the browser UI when processing data.
 | ||||||
|  | 		fetch( href ) | ||||||
|  | 			.then( resource => resource.blob() ) | ||||||
|  | 			.then( blob => { | ||||||
|  | 				const mimeType = getFileMimeType( blob, href ); | ||||||
|  | 				const ext = mimeType.replace( 'file/', '' ); | ||||||
|  | 				const filename = `file.${ ext }`; | ||||||
|  | 				const file = createFileFromBlob( blob, filename, mimeType ); | ||||||
|  | 
 | ||||||
|  | 				file ? resolve( file ) : reject(); | ||||||
|  | 			} ) | ||||||
|  | 			.catch( reject ); | ||||||
|  | 	} ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function isLocalFile( node ) { | ||||||
|  | 	if ( !node.is( 'element', 'a' ) || !node.getAttribute( 'href' ) ) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return node.getAttribute( 'href' ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getFileMimeType( blob, src ) { | ||||||
|  | 	if ( blob.type ) { | ||||||
|  | 		return blob.type; | ||||||
|  | 	} else if ( src.match( /data:(image\/\w+);base64/ ) ) { | ||||||
|  | 		return src.match( /data:(image\/\w+);base64/ )[ 1 ].toLowerCase(); | ||||||
|  | 	} else { | ||||||
|  | 		throw new Error( 'Could not retrieve mime type for file.' ); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function createFileFromBlob( blob, filename, mimeType ) { | ||||||
|  | 	try { | ||||||
|  | 		return new File( [ blob ], filename, { type: mimeType } ); | ||||||
|  | 	} catch ( err ) { | ||||||
|  | 		// Edge does not support `File` constructor ATM, see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9551546/.
 | ||||||
|  | 		// However, the `File` function is present (so cannot be checked with `!window.File` or `typeof File === 'function'`), but
 | ||||||
|  | 		// calling it with `new File( ... )` throws an error. This try-catch prevents that. Also when the function will
 | ||||||
|  | 		// be implemented correctly in Edge the code will start working without any changes (see #247).
 | ||||||
|  | 		return null; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Returns `true` if non-empty `text/html` is included in the data transfer.
 | ||||||
|  | //
 | ||||||
|  | // @param {module:clipboard/datatransfer~DataTransfer} dataTransfer
 | ||||||
|  | // @returns {Boolean}
 | ||||||
|  | export function isHtmlIncluded( dataTransfer ) { | ||||||
|  | 	return Array.from( dataTransfer.types ).includes( 'text/html' ) && dataTransfer.getData( 'text/html' ) !== ''; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getFileLinksFromChangeItem( editor, item ) { | ||||||
|  | 	return Array.from( editor.model.createRangeOn( item ) ) | ||||||
|  | 		.filter( value => value.item.hasAttribute( 'href' ) ) | ||||||
|  | 		.map( value => value.item ); | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								_regroup/ckeditor5-file-upload/theme/fileupload.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								_regroup/ckeditor5-file-upload/theme/fileupload.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | .ck.ck-sticky-panel > .ck-progress-bar { | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: row; | ||||||
|  | 	justify-content: space-between; | ||||||
|  | 
 | ||||||
|  | 	border-left: 1px solid var(--ck-color-base-border); | ||||||
|  | 	border-top: 1px solid var(--ck-color-base-border); | ||||||
|  | 	border-right: 1px solid var(--ck-color-base-border); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .ck.ck-sticky-panel > .ck-progress-bar > .ck-uploading-progress { | ||||||
|  | 	align-self: center; | ||||||
|  | 	padding: 3px 5px; | ||||||
|  | 	font-weight: bold; | ||||||
|  | 
 | ||||||
|  | 	color: var(--ck-color-base-foreground); | ||||||
|  | 	background-color: var(--ck-color-base-border); | ||||||
|  | 
 | ||||||
|  | 	transition-property: width; | ||||||
|  | 	transition-duration: .5s; | ||||||
|  | 	transition-timing-function: linear; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .ck.ck-sticky-panel > .ck-progress-bar > .ck-uploading-cancel { | ||||||
|  | 	align-self: flex-end; | ||||||
|  | 	padding: 0 5px; | ||||||
|  | 	font-weight: bold; | ||||||
|  | 	color: var(--ck-color-base-error); | ||||||
|  | } | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon --> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||||||
|  | <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve"> | ||||||
|  | <metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata> | ||||||
|  | <g><g transform="translate(0.000000,511.000000) scale(0.100000,-0.100000)"><path d="M1443.6,4990.4c-26.9-11.5-69.2-38.4-92.2-61.5c-107.6-99.9-99.9,232.5-99.9-4823.9v-4677.8l42.3-63.4c25-34.6,69.2-82.6,98-103.8c53.8-40.3,57.7-40.3,1966.1-40.3h1910.3l51.9,53.8c51.9,50,53.8,59.6,53.8,246v194.1l-63.4,55.7l-61.5,55.7H3557.7H1866.4V110.8v4285.8H3894h2027.6v-945.6c0-622.7,7.7-974.4,21.2-1024.3c11.5-42.3,44.2-101.9,71.1-132.6c101.9-107.6,92.2-107.6,1147.4-107.6h970.5V716.1c0-1633.6-5.8-1560.6,124.9-1616.3c84.6-34.6,280.6-34.6,363.2,0c136.4,55.7,126.8-67.3,126.8,1795c0,1620.1-1.9,1679.7-36.5,1748.9c-55.7,105.7-2262,2300.5-2350.4,2338.9c-63.4,25-351.7,28.8-2469.6,26.9C2345,5009.6,1474.4,5001.9,1443.6,4990.4z M7132.3,3368.3l567-567h-572.7h-570.8v567c0,311.3,1.9,567,5.8,567C6563.4,3935.3,6821,3679.6,7132.3,3368.3z"/><path d="M6242.5-1670.8c-411.3-411.3-772.6-784.1-803.3-830.2c-157.6-242.1,55.7-536.2,334.4-463.2c69.2,19.2,144.1,86.5,522.7,463.2c244.1,242.2,449.7,440.1,457.4,440.1c5.8,0,15.4-572.7,17.3-1272.3c5.8-1239.6,7.7-1276.1,44.2-1326.1c48-67.3,174.9-130.7,257.5-130.7c90.3,0,203.7,65.4,253.7,148l46.1,73l5.8,1256.9l5.8,1258.8l445.9-443.9c388.2-388.2,457.4-447.8,532.4-467c251.8-67.3,468.9,192.2,355.5,430.5c-15.4,32.7-376.7,407.4-803.3,834.1C7157.3-944.4,7140-927.1,7065-927.1S6972.8-944.4,6242.5-1670.8z"/></g></g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										68
									
								
								_regroup/ckeditor5-file-upload/theme/progressbarview.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								_regroup/ckeditor5-file-upload/theme/progressbarview.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | |||||||
|  | import View from "@ckeditor/ckeditor5-ui/src/view"; | ||||||
|  | import toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit'; | ||||||
|  | import ButtonView from "@ckeditor/ckeditor5-ui/src/button/buttonview"; | ||||||
|  | 
 | ||||||
|  | import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg'; | ||||||
|  | 
 | ||||||
|  | const toPx = toUnit('%'); | ||||||
|  | 
 | ||||||
|  | export default class ProgressBarView extends View { | ||||||
|  | 	constructor(locale) { | ||||||
|  | 		super(locale); | ||||||
|  | 
 | ||||||
|  | 		const bind = this.bindTemplate; | ||||||
|  | 		this.cancelButton = this._createCancelButton(locale); | ||||||
|  | 
 | ||||||
|  | 		// Views define their interface (state) using observable attributes.
 | ||||||
|  | 		this.set('width', 100); | ||||||
|  | 		this.set('customWidth', 0); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 		this.setTemplate({ | ||||||
|  | 			tag: 'div', | ||||||
|  | 
 | ||||||
|  | 			// The element of the view can be defined with its children.
 | ||||||
|  | 			children: [ | ||||||
|  | 				{ | ||||||
|  | 					tag: 'div', | ||||||
|  | 					children: ['Uploading...'], | ||||||
|  | 					attributes: { | ||||||
|  | 						class: ['ck-uploading-progress'], | ||||||
|  | 						style: { | ||||||
|  | 							width: bind.to('customWidth', toPx), | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				}, | ||||||
|  | 				this.cancelButton, | ||||||
|  | 			], | ||||||
|  | 			attributes: { | ||||||
|  | 				class: [ | ||||||
|  | 					'ck-progress-bar', | ||||||
|  | 
 | ||||||
|  | 					// Observable attributes control the state of the view in DOM.
 | ||||||
|  | 					bind.to('elementClass') | ||||||
|  | 				], | ||||||
|  | 				style: { | ||||||
|  | 					width: bind.to('width', toPx), | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_createCancelButton(locale) { | ||||||
|  | 		const view = new ButtonView(locale); | ||||||
|  | 		view.set({ | ||||||
|  | 			icon: cancelIcon, | ||||||
|  | 			tooltip: true, | ||||||
|  | 			label: 'Cancel', | ||||||
|  | 			attributes: { | ||||||
|  | 				class: ['ck', 'ck-button', 'ck-off', 'ck-button-cancel', 'ck-uploading-cancel'] | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		view.on('execute', () => { | ||||||
|  | 			this.fire('cancel') | ||||||
|  | 		}); | ||||||
|  | 		return view; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								_regroup/ckeditor5-file-upload/uploadfileplugin.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								_regroup/ckeditor5-file-upload/uploadfileplugin.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | import { Plugin } from 'ckeditor5/src/core'; | ||||||
|  | import FileUploadEditing from './src/fileuploadediting'; | ||||||
|  | 
 | ||||||
|  | export default class Uploadfileplugin extends Plugin { | ||||||
|  | 	static get requires() { | ||||||
|  | 		return [ FileUploadEditing ]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	static get pluginName() { | ||||||
|  | 		return 'fileUploadPlugin'; | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran