mirror of
https://github.com/zadam/trilium.git
synced 2025-11-09 06:45:49 +01:00
chore(ckeditor5-math): integrate source code
This commit is contained in:
133
packages/ckeditor5-math/src/automath.ts
Normal file
133
packages/ckeditor5-math/src/automath.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { Clipboard, Plugin, type Editor, LivePosition, LiveRange, Undo } from 'ckeditor5';
|
||||
import { extractDelimiters, hasDelimiters, delimitersCounts } from './utils.js';
|
||||
|
||||
export default class AutoMath extends Plugin {
|
||||
public static get requires() {
|
||||
return [ Clipboard, Undo ] as const;
|
||||
}
|
||||
|
||||
public static get pluginName() {
|
||||
return 'AutoMath' as const;
|
||||
}
|
||||
|
||||
private _timeoutId: null | number;
|
||||
private _positionToInsert: null | LivePosition;
|
||||
|
||||
constructor( editor: Editor ) {
|
||||
super( editor );
|
||||
|
||||
this._timeoutId = null;
|
||||
|
||||
this._positionToInsert = null;
|
||||
}
|
||||
|
||||
public init(): void {
|
||||
const editor = this.editor;
|
||||
const modelDocument = editor.model.document;
|
||||
|
||||
this.listenTo( editor.plugins.get( Clipboard ), 'inputTransformation', () => {
|
||||
const firstRange = modelDocument.selection.getFirstRange();
|
||||
if ( !firstRange ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const leftLivePosition = LivePosition.fromPosition( firstRange.start );
|
||||
leftLivePosition.stickiness = 'toPrevious';
|
||||
|
||||
const rightLivePosition = LivePosition.fromPosition( firstRange.end );
|
||||
rightLivePosition.stickiness = 'toNext';
|
||||
|
||||
modelDocument.once( 'change:data', () => {
|
||||
this._mathBetweenPositions(
|
||||
leftLivePosition,
|
||||
rightLivePosition
|
||||
);
|
||||
|
||||
leftLivePosition.detach();
|
||||
rightLivePosition.detach();
|
||||
},
|
||||
{ priority: 'high' }
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
editor.commands.get( 'undo' )?.on( 'execute', () => {
|
||||
if ( this._timeoutId ) {
|
||||
window.clearTimeout( this._timeoutId );
|
||||
this._positionToInsert?.detach();
|
||||
|
||||
this._timeoutId = null;
|
||||
this._positionToInsert = null;
|
||||
}
|
||||
}, { priority: 'high' } );
|
||||
}
|
||||
|
||||
private _mathBetweenPositions(
|
||||
leftPosition: LivePosition,
|
||||
rightPosition: LivePosition
|
||||
) {
|
||||
const editor = this.editor;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const mathConfig = this.editor.config.get( 'math' );
|
||||
|
||||
const equationRange = new LiveRange( leftPosition, rightPosition );
|
||||
const walker = equationRange.getWalker( { ignoreElementEnd: true } );
|
||||
|
||||
let text = '';
|
||||
|
||||
// Get equation text
|
||||
for ( const node of walker ) {
|
||||
if ( node.item.is( '$textProxy' ) ) {
|
||||
text += node.item.data;
|
||||
}
|
||||
}
|
||||
|
||||
text = text.trim();
|
||||
|
||||
// Skip if don't have delimiters
|
||||
if ( !hasDelimiters( text ) || delimitersCounts( text ) !== 2 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mathCommand = editor.commands.get( 'math' );
|
||||
|
||||
// Do not anything if math element cannot be inserted at the current position
|
||||
if ( !mathCommand?.isEnabled ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._positionToInsert = LivePosition.fromPosition( leftPosition );
|
||||
|
||||
// With timeout user can undo conversation if want use plain text
|
||||
this._timeoutId = window.setTimeout( () => {
|
||||
editor.model.change( writer => {
|
||||
this._timeoutId = null;
|
||||
|
||||
writer.remove( equationRange );
|
||||
|
||||
let insertPosition: LivePosition | null;
|
||||
|
||||
// Check if position where the math element should be inserted is still valid.
|
||||
if ( this._positionToInsert?.root.rootName !== '$graveyard' ) {
|
||||
insertPosition = this._positionToInsert;
|
||||
}
|
||||
|
||||
editor.model.change( innerWriter => {
|
||||
const params = Object.assign( extractDelimiters( text ), {
|
||||
type: mathConfig?.outputType
|
||||
} );
|
||||
const mathElement = innerWriter.createElement( params.display ? 'mathtex-display' : 'mathtex-inline', params
|
||||
);
|
||||
|
||||
editor.model.insertContent( mathElement, insertPosition );
|
||||
|
||||
innerWriter.setSelection( mathElement, 'on' );
|
||||
} );
|
||||
|
||||
this._positionToInsert?.detach();
|
||||
this._positionToInsert = null;
|
||||
} );
|
||||
}, 100 );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user