- Added comprehensive AI Assistant system (aiassist/ directory): * Vector search and embedding capabilities * Typebot proxy integration * Elastic search functionality * Message classification and chat history * MCP proxy for external integrations - Implemented Court Status API (GetCourtStatus.php): * Real-time court document status checking * Integration with external court systems * Comprehensive error handling and logging - Enhanced S3 integration: * Improved file backup system with metadata * Batch processing capabilities * Enhanced error logging and recovery * Copy operations with URL fixing - Added Telegram contact creation API - Improved error logging across all modules - Enhanced callback system for AI responses - Extensive backup file storage with timestamps - Updated documentation and README files - File storage improvements: * Thousands of backup files with proper metadata * Fix operations for broken file references * Project-specific backup and recovery systems * Comprehensive file integrity checking Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
296 lines
7.6 KiB
JavaScript
296 lines
7.6 KiB
JavaScript
/**
|
|
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
|
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
( function() {
|
|
|
|
CKEDITOR.plugins.add( 'textwatcher', {} );
|
|
|
|
/**
|
|
* API exposed by the [Text Watcher](https://ckeditor.com/cke4/addon/textwatcher) plugin.
|
|
*
|
|
* Class implementing the text watcher — a base for features like
|
|
* autocomplete. It fires the {@link #matched} and {@link #unmatched} events
|
|
* based on changes in the text and the position of the caret in the editor.
|
|
*
|
|
* To check whether the text matches some criteria, the text watcher uses
|
|
* a callback function which should return the matching text and a {@link CKEDITOR.dom.range}
|
|
* for that text.
|
|
*
|
|
* Since the text watcher works on the DOM where searching for text
|
|
* is pretty complicated, it is usually recommended to use the {@link CKEDITOR.plugins.textMatch#match}
|
|
* function.
|
|
*
|
|
* Example:
|
|
*
|
|
* ```javascript
|
|
* function textTestCallback( range ) {
|
|
* // You do not want to autocomplete a non-empty selection.
|
|
* if ( !range.collapsed ) {
|
|
* return null;
|
|
* }
|
|
*
|
|
* // Use the text match plugin which does the tricky job of doing
|
|
* // a text search in the DOM. The matchCallback function should return
|
|
* // a matching fragment of the text.
|
|
* return CKEDITOR.plugins.textMatch.match( range, matchCallback );
|
|
* }
|
|
*
|
|
* function matchCallback( text, offset ) {
|
|
* // Get the text before the caret.
|
|
* var left = text.slice( 0, offset ),
|
|
* // Will look for an '@' character followed by word characters.
|
|
* match = left.match( /@\w*$/ );
|
|
*
|
|
* if ( !match ) {
|
|
* return null;
|
|
* }
|
|
* return { start: match.index, end: offset };
|
|
* }
|
|
*
|
|
* // Initialize the text watcher.
|
|
* var textWatcher = new CKEDITOR.plugins.textWatcher( editor, textTestCallback );
|
|
* // Start listening.
|
|
* textWatcher.attach();
|
|
*
|
|
* // Handle text matching.
|
|
* textWatcher.on( 'matched', function( evt ) {
|
|
* autocomplete.setQuery( evt.data.text );
|
|
* } );
|
|
* ```
|
|
*
|
|
* @class CKEDITOR.plugins.textWatcher
|
|
* @since 4.10.0
|
|
* @mixins CKEDITOR.event
|
|
* @constructor Creates the text watcher instance.
|
|
* @param {CKEDITOR.editor} editor The editor instance to watch in.
|
|
* @param {Function} callback Callback executed when the text watcher
|
|
* thinks that something might have changed.
|
|
* @param {Number} [throttle=0] Throttle interval, see {@link #throttle}.
|
|
* @param {CKEDITOR.dom.range} callback.range The range representing the caret position.
|
|
* @param {Object} [callback.return=null] Matching text data (`null` if nothing matches).
|
|
* @param {String} callback.return.text The matching text.
|
|
* @param {CKEDITOR.dom.range} callback.return.range A range in the DOM for the text that matches.
|
|
*/
|
|
function TextWatcher( editor, callback, throttle ) {
|
|
/**
|
|
* The editor instance which the text watcher watches.
|
|
*
|
|
* @readonly
|
|
* @property {CKEDITOR.editor}
|
|
*/
|
|
this.editor = editor;
|
|
|
|
/**
|
|
* The last matched text.
|
|
*
|
|
* @readonly
|
|
* @property {String}
|
|
*/
|
|
this.lastMatched = null;
|
|
|
|
/**
|
|
* Whether the next check should be ignored. See the {@link #consumeNext} method.
|
|
*
|
|
* @readonly
|
|
*/
|
|
this.ignoreNext = false;
|
|
|
|
/**
|
|
* The callback passed to the {@link CKEDITOR.plugins.textWatcher} constructor.
|
|
*
|
|
* @readonly
|
|
* @property {Function}
|
|
*/
|
|
this.callback = callback;
|
|
|
|
/**
|
|
* Keys that should be ignored by the {@link #check} method.
|
|
*
|
|
* @readonly
|
|
* @property {Number[]}
|
|
*/
|
|
this.ignoredKeys = [
|
|
16, // Shift
|
|
17, // Ctrl
|
|
18, // Alt
|
|
91, // Cmd
|
|
35, // End
|
|
36, // Home
|
|
37, // Left
|
|
38, // Up
|
|
39, // Right
|
|
40, // Down
|
|
33, // PageUp
|
|
34 // PageUp
|
|
];
|
|
|
|
/**
|
|
* Listeners registered by this text watcher.
|
|
*
|
|
* @private
|
|
*/
|
|
this._listeners = [];
|
|
|
|
/**
|
|
* Indicates throttle threshold mitigating text checks.
|
|
*
|
|
* Higher levels of the throttle threshold will create a delay for text watcher checks
|
|
* but also improve its performance.
|
|
*
|
|
* See the {@link CKEDITOR.tools#throttle throttle} feature for more information.
|
|
*
|
|
* @readonly
|
|
* @property {Number} [throttle=0]
|
|
*/
|
|
this.throttle = throttle || 0;
|
|
|
|
/**
|
|
* The {@link CKEDITOR.tools#throttle throttle buffer} used to mitigate text checks.
|
|
*
|
|
* @private
|
|
*/
|
|
this._buffer = CKEDITOR.tools.throttle( this.throttle, testTextMatch, this );
|
|
|
|
/**
|
|
* Event fired when the text is no longer matching.
|
|
*
|
|
* @event matched
|
|
* @param {Object} data The value returned by the {@link #callback}.
|
|
* @param {String} data.text
|
|
* @param {CKEDITOR.dom.range} data.range
|
|
*/
|
|
|
|
/**
|
|
* Event fired when the text stops matching.
|
|
*
|
|
* @event unmatched
|
|
*/
|
|
|
|
function testTextMatch( selectionRange ) {
|
|
var matched = this.callback( selectionRange );
|
|
|
|
if ( matched ) {
|
|
if ( matched.text == this.lastMatched ) {
|
|
return;
|
|
}
|
|
|
|
this.lastMatched = matched.text;
|
|
this.fire( 'matched', matched );
|
|
} else if ( this.lastMatched ) {
|
|
this.unmatch();
|
|
}
|
|
}
|
|
}
|
|
|
|
TextWatcher.prototype = {
|
|
/**
|
|
* Attaches the text watcher to the {@link #editor}.
|
|
*
|
|
* @chainable
|
|
*/
|
|
attach: function() {
|
|
var editor = this.editor;
|
|
|
|
this._listeners.push( editor.on( 'contentDom', onContentDom, this ) );
|
|
this._listeners.push( editor.on( 'blur', unmatch, this ) );
|
|
this._listeners.push( editor.on( 'beforeModeUnload', unmatch, this ) );
|
|
this._listeners.push( editor.on( 'setData', unmatch, this ) );
|
|
this._listeners.push( editor.on( 'afterCommandExec', unmatch, this ) );
|
|
|
|
// Attach if editor is already initialized.
|
|
if ( editor.editable() ) {
|
|
onContentDom.call( this );
|
|
}
|
|
|
|
return this;
|
|
|
|
function onContentDom() {
|
|
var editable = editor.editable();
|
|
|
|
this._listeners.push( editable.attachListener( editable, 'keyup', check, this ) );
|
|
}
|
|
|
|
// CKEditor's event system has a limitation that one function (in this case this.check)
|
|
// cannot be used as listener for the same event more than once. Hence, wrapper function.
|
|
function check( evt ) {
|
|
this.check( evt );
|
|
}
|
|
|
|
function unmatch() {
|
|
this.unmatch();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Triggers a text check. Fires the {@link #matched} and {@link #unmatched} events.
|
|
* The {@link #matched} event will not be fired twice in a row for the same text
|
|
* unless the text watcher is {@link #unmatch reset}.
|
|
*
|
|
* @param {CKEDITOR.dom.event/CKEDITOR.eventInfo} [evt]
|
|
*/
|
|
check: function( evt ) {
|
|
if ( this.ignoreNext ) {
|
|
this.ignoreNext = false;
|
|
return;
|
|
}
|
|
|
|
// Ignore control keys, so they don't trigger the check.
|
|
if ( evt && evt.name == 'keyup' && ( CKEDITOR.tools.array.indexOf( this.ignoredKeys, evt.data.getKey() ) != -1 ) ) {
|
|
return;
|
|
}
|
|
|
|
var sel = this.editor.getSelection();
|
|
if ( !sel ) {
|
|
return;
|
|
}
|
|
|
|
var selectionRange = sel.getRanges()[ 0 ];
|
|
if ( !selectionRange ) {
|
|
return;
|
|
}
|
|
|
|
this._buffer.input( selectionRange );
|
|
},
|
|
|
|
/**
|
|
* Ignores the next {@link #check}.
|
|
*
|
|
* @chainable
|
|
*/
|
|
consumeNext: function() {
|
|
this.ignoreNext = true;
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Resets the state and fires the {@link #unmatched} event.
|
|
*
|
|
* @chainable
|
|
*/
|
|
unmatch: function() {
|
|
this.lastMatched = null;
|
|
this.fire( 'unmatched' );
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Destroys the text watcher instance. The DOM event listeners will be cleaned up.
|
|
*/
|
|
destroy: function() {
|
|
CKEDITOR.tools.array.forEach( this._listeners, function( obj ) {
|
|
obj.removeListener();
|
|
} );
|
|
this._listeners = [];
|
|
}
|
|
};
|
|
|
|
CKEDITOR.event.implementOn( TextWatcher.prototype );
|
|
|
|
CKEDITOR.plugins.textWatcher = TextWatcher;
|
|
|
|
} )();
|