diff --git a/packages/ckeditor5-math/src/mathediting.ts b/packages/ckeditor5-math/src/mathediting.ts index bfd08ed37..0c51653c3 100644 --- a/packages/ckeditor5-math/src/mathediting.ts +++ b/packages/ckeditor5-math/src/mathediting.ts @@ -27,6 +27,18 @@ export default class MathEditing extends Plugin { public init(): void { const editor = this.editor; + + const originalProcessor = editor.data.processor; + const originalToView = originalProcessor.toView.bind(originalProcessor); + const mathSpanRegex = /([\s\S]*?)<\/span>/g; + originalProcessor.toView = (data: string) => { + // Preprocessing: preserve line breaks inside math formulas by replacing \n with + const processedData = data.replace(mathSpanRegex, (_, content) => + `${content.replace(/\n/g, '___MATH_TEX_LF___')}` + ); + return originalToView(processedData); + }; + editor.commands.add( 'math', new MathCommand( editor ) ); this._defineSchema(); @@ -120,8 +132,7 @@ export default class MathEditing extends Plugin { model: ( viewElement, { writer } ) => { const child = viewElement.getChild( 0 ); if ( child?.is( '$text' ) ) { - const equation = child.data.trim(); - + const equation = child.data.trim().replace(/___MATH_TEX_LF___/g, '\n'); const params = Object.assign( extractDelimiters( equation ), { type: mathConfig.forceOutputType ? mathConfig.outputType : diff --git a/packages/ckeditor5-math/src/mathui.ts b/packages/ckeditor5-math/src/mathui.ts index f3c86af49..851c86e63 100644 --- a/packages/ckeditor5-math/src/mathui.ts +++ b/packages/ckeditor5-math/src/mathui.ts @@ -110,6 +110,27 @@ export default class MathUI extends Plugin { cancel(); } ); + // Allow pressing Enter to submit changes, and use Shift+Enter to insert a new line + formView.keystrokes.set('enter', (data, cancel) => { + if (!data.shiftKey) { + formView.fire('submit'); + cancel(); + } + }); + + // Allow the textarea to be resizable + formView.mathInputView.fieldView.once('render', () => { + const textarea = formView.mathInputView.fieldView.element; + if (!textarea) return; + textarea.focus(); + Object.assign(textarea.style, { + resize: 'both', + height: '100px', + width: '400px', + minWidth: '100%', + }); + }); + return formView; } diff --git a/packages/ckeditor5-math/src/ui/mainformview.ts b/packages/ckeditor5-math/src/ui/mainformview.ts index af86fd77c..751c3c679 100644 --- a/packages/ckeditor5-math/src/ui/mainformview.ts +++ b/packages/ckeditor5-math/src/ui/mainformview.ts @@ -1,16 +1,16 @@ -import { ButtonView, createLabeledInputText, FocusCycler, LabelView, LabeledFieldView, submitHandler, SwitchButtonView, View, ViewCollection, type InputTextView, type FocusableView, Locale, FocusTracker, KeystrokeHandler } from 'ckeditor5'; +import { ButtonView, createLabeledTextarea, FocusCycler, LabelView, LabeledFieldView, submitHandler, SwitchButtonView, View, ViewCollection, type TextareaView, type FocusableView, Locale, FocusTracker, KeystrokeHandler } from 'ckeditor5'; import { IconCheck, IconCancel } from "@ckeditor/ckeditor5-icons"; import { extractDelimiters, hasDelimiters } from '../utils.js'; import MathView from './mathview.js'; import '../../theme/mathform.css'; import type { KatexOptions } from '../typings-external.js'; -class MathInputView extends LabeledFieldView { +class MathInputView extends LabeledFieldView { public value: null | string = null; public isReadOnly = false; constructor( locale: Locale ) { - super( locale, createLabeledInputText ); + super( locale, createLabeledTextarea ); } } diff --git a/packages/ckeditor5-math/src/ui/mathview.ts b/packages/ckeditor5-math/src/ui/mathview.ts index 541227e43..fab16262e 100644 --- a/packages/ckeditor5-math/src/ui/mathview.ts +++ b/packages/ckeditor5-math/src/ui/mathview.ts @@ -49,7 +49,7 @@ export default class MathView extends View { this.setTemplate( { tag: 'div', attributes: { - class: [ 'ck', 'ck-math-preview' ] + class: [ 'ck', 'ck-math-preview', 'ck-reset_all-excluded' ] } } ); } diff --git a/packages/ckeditor5-math/src/utils.ts b/packages/ckeditor5-math/src/utils.ts index 3a29d3fc2..2e120b6c2 100644 --- a/packages/ckeditor5-math/src/utils.ts +++ b/packages/ckeditor5-math/src/utils.ts @@ -94,7 +94,6 @@ export async function renderEquation( el => { renderMathJax3( equation, el, display, () => { if ( preview ) { - moveAndScaleElement( element, el ); el.style.visibility = 'visible'; } } ); @@ -115,7 +114,6 @@ export async function renderEquation( if ( preview && isMathJaxVersion2( MathJax ) ) { // eslint-disable-next-line new-cap MathJax.Hub.Queue( () => { - moveAndScaleElement( element, el ); el.style.visibility = 'visible'; } ); } @@ -139,7 +137,6 @@ export async function renderEquation( } ); } if ( preview ) { - moveAndScaleElement( element, el ); el.style.visibility = 'visible'; } } @@ -295,47 +292,7 @@ function getPreviewElement( previewEl.setAttribute( 'id', previewUid ); previewEl.classList.add( ...previewClassName ); previewEl.style.visibility = 'hidden'; - document.body.appendChild( previewEl ); - - let ticking = false; - - const renderTransformation = () => { - if ( !ticking ) { - window.requestAnimationFrame( () => { - if ( previewEl ) { - moveElement( element, previewEl ); - ticking = false; - } - } ); - - ticking = true; - } - }; - - // Create scroll listener for following - window.addEventListener( 'resize', renderTransformation ); - window.addEventListener( 'scroll', renderTransformation ); + element.appendChild( previewEl ); } return previewEl; } - -function moveAndScaleElement( parent: HTMLElement, child: HTMLElement ) { - // Move to right place - moveElement( parent, child ); - - // Scale parent element same as preview - const domRect = child.getBoundingClientRect(); - parent.style.width = domRect.width + 'px'; - parent.style.height = domRect.height + 'px'; -} - -function moveElement( parent: HTMLElement, child: HTMLElement ) { - const domRect = parent.getBoundingClientRect(); - const left = window.scrollX + domRect.left; - const top = window.scrollY + domRect.top; - child.style.position = 'absolute'; - child.style.left = left + 'px'; - child.style.top = top + 'px'; - child.style.zIndex = 'var(--ck-z-panel)'; - child.style.pointerEvents = 'none'; -}