Add preview fix

This commit is contained in:
Sauli Anto 2019-10-03 03:47:26 +03:00
parent e6605706c0
commit b7ccab38ff
5 changed files with 144 additions and 84 deletions

View File

@ -64,7 +64,7 @@ export default class MathUI extends Plugin {
...this.editor.config.get( 'math' )
};
const formView = new MainFormView( editor.locale, mathConfig.engine );
const formView = new MainFormView( editor.locale, mathConfig.engine, mathConfig.enablePreview );
formView.mathInputView.bind( 'value' ).to( mathCommand, 'value' );
formView.displayButtonView.bind( 'isOn' ).to( mathCommand, 'display' );
@ -106,6 +106,13 @@ export default class MathUI extends Plugin {
this._form.mathInputView.select();
}
// Show preview element
const elId = 'math-preview';
let prewviewEl = document.getElementById( elId );// eslint-disable-line
if ( prewviewEl ) {
prewviewEl.style.display = 'block';
}
this._form.equation = mathCommand.value || '';
this._form.displayButtonView.isOn = mathCommand.display || false;
}
@ -141,6 +148,13 @@ export default class MathUI extends Plugin {
this._balloon.remove( this._form );
// Hide preview element
const elId = 'math-preview';
let prewviewEl = document.getElementById( elId );// eslint-disable-line
if ( prewviewEl ) {
prewviewEl.style.display = 'none';
}
this.editor.editing.view.focus();
}
}

View File

@ -22,7 +22,7 @@ import MathView from './mathview';
import '../../theme/mathform.css';
export default class MainFormView extends View {
constructor( locale, engine ) {
constructor( locale, engine, previewEnabled ) {
super( locale );
const t = locale.t;
@ -33,10 +33,6 @@ export default class MainFormView extends View {
// Equation input
this.mathInputView = this._createMathInput();
// Fixme:
// Preview isn't available in katex, because .ck-reset_all * css rule breaks it
this.previewEnabled = engine !== 'katex' || true;
// Display button
this.displayButtonView = this._createDisplayButton();
@ -47,11 +43,12 @@ export default class MainFormView extends View {
// Cancel button
this.cancelButtonView = this._createButton( t( 'Cancel' ), cancelIcon, 'ck-button-cancel', 'cancel' );
// Preview label
this.previewLabel = new LabelView( locale );
this.previewEnabled = previewEnabled;
let children = [];
if ( this.previewEnabled ) {
// Preview label
this.previewLabel = new LabelView( locale );
this.previewLabel.text = t( 'Equation preview' );
// Math element
@ -65,11 +62,9 @@ export default class MainFormView extends View {
this.mathView
];
} else {
this.previewLabel.text = t( 'Equation preview isn\'t available' );
children = [
this.mathInputView,
this.displayButtonView,
this.previewLabel
this.displayButtonView
];
}

View File

@ -16,7 +16,7 @@ export default class MathView extends View {
} );
this.setTemplate( {
tag: 'iframe',
tag: 'div',
attributes: {
class: [
'ck',
@ -29,40 +29,7 @@ export default class MathView extends View {
updateMath() {
const el = this.element;
if ( el ) {
// Fixme
// eslint-disable-next-line
setTimeout( () => {
let docEl = ( el.contentWindow || el.contentDocument );
if ( docEl.document ) {
docEl = docEl.document;
}
const headEl = docEl.head;
// Remove old styles
while ( headEl.hasChildNodes() ) {
headEl.removeChild( headEl.firstChild );
}
// Add all MathJax styles
const styles = document.head.getElementsByTagName( 'style' ); // eslint-disable-line
for ( const style of styles ) {
const id = style.getAttribute( 'id' );
if ( id && id.startsWith( 'MJX' ) ) {
headEl.appendChild( style.cloneNode( true ) );
}
}
const links = document.head.getElementsByTagName( 'link' ); // eslint-disable-line
for ( const link of links ) {
headEl.appendChild( link.cloneNode( true ) );
}
const bodyEl = docEl.body;
bodyEl.setAttribute( 'style', 'margin-left: 0; margin-right: 0; user-select: none;' );
renderEquation( this.value, bodyEl, this.engine, this.display );
}, 100 );
renderEquation( this.value, el, this.engine, this.display, true );
}
}

View File

@ -1,7 +1,8 @@
export const defaultConfig = {
engine: 'mathjax',
outputType: 'script',
forceOutputType: false
forceOutputType: false,
enablePreview: true
};
export function getSelectedMathModelWidget( selection ) {
@ -14,47 +15,30 @@ export function getSelectedMathModelWidget( selection ) {
return null;
}
export function renderEquation( equation, element, engine = 'katex', display = false ) {
export function renderEquation( equation, element, engine = 'katex', display = false, previewHack = false ) {
if ( engine === 'mathjax' && typeof MathJax !== 'undefined' ) {
if ( isMathJaxVersion3( MathJax.version ) ) {
const options = MathJax.getMetricsFor( element, display );
let promiseFunction = undefined;
if ( typeof MathJax.tex2chtmlPromise !== 'undefined' ) {
promiseFunction = MathJax.tex2chtmlPromise;
} else if ( typeof MathJax.tex2svgPromise !== 'undefined' ) {
promiseFunction = MathJax.tex2svgPromise;
}
if ( typeof promiseFunction !== 'undefined' ) {
promiseFunction( equation, options ).then( node => {
if ( element.firstChild ) {
element.firstChild.replaceWith( node );
} else {
element.appendChild( node );
selectRenderMode( element, previewHack, el => {
renderMathJax3( equation, el, display, () => {
if ( previewHack ) {
moveAndScaleElement( element, el );
}
MathJax.startup.document.clear();
MathJax.startup.document.updateDocument();
} );
}
} );
} else {
// Fixme: MathJax typesetting cause occasionally math processing error without asynchronous call
// eslint-disable-next-line
setTimeout( () => {
if ( display ) {
element.innerHTML = '\\[' + equation + '\\]';
} else {
element.innerHTML = '\\(' + equation + '\\)';
}
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, element ] ); // eslint-disable-line
selectRenderMode( element, previewHack, el => {
renderMathJax2( equation, el, display );
} );
}
} else if ( engine === 'katex' && typeof katex !== 'undefined' ) {
katex.render( equation, element, {
throwOnError: false,
displayMode: display
selectRenderMode( element, previewHack, el => {
katex.render( equation, el, {
throwOnError: false,
displayMode: display
} );
} );
} else if ( typeof engine === 'function' ) {
engine( equation, element, display );
engine( equation, element, display, previewHack );
} else {
element.innerHTML = equation;
// eslint-disable-next-line
@ -62,6 +46,107 @@ export function renderEquation( equation, element, engine = 'katex', display = f
}
}
function selectRenderMode( element, preview, cb ) {
if ( preview ) {
createPreviewElement( element, prewviewEl => {
cb( prewviewEl );
} );
} else {
cb( element );
}
}
function renderMathJax3( equation, element, display, after ) {
const options = MathJax.getMetricsFor( element, display );
let promiseFunction = undefined;
if ( typeof MathJax.tex2chtmlPromise !== 'undefined' ) {
promiseFunction = MathJax.tex2chtmlPromise;
} else if ( typeof MathJax.tex2svgPromise !== 'undefined' ) {
promiseFunction = MathJax.tex2svgPromise;
}
if ( typeof promiseFunction !== 'undefined' ) {
promiseFunction( equation, options ).then( node => {
if ( element.firstChild ) {
element.firstChild.replaceWith( node );
} else {
element.appendChild( node );
}
MathJax.startup.document.clear();
MathJax.startup.document.updateDocument();
after();
} );
}
}
function renderMathJax2( equation, element, display ) {
// Fixme: MathJax typesetting cause occasionally math processing error without asynchronous call
// eslint-disable-next-line
setTimeout( () => {
if ( display ) {
element.innerHTML = '\\[' + equation + '\\]';
} else {
element.innerHTML = '\\(' + equation + '\\)';
}
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, element ] ); // eslint-disable-line
} );
}
function createPreviewElement( element, render ) {
const prewviewEl = getPreviewElement( element );
render( prewviewEl );
moveAndScaleElement( element, prewviewEl );
}
export function getPreviewElement( element ) {
const elId = 'math-preview';
let prewviewEl = document.getElementById( elId ); // eslint-disable-line
if ( !prewviewEl ) {
prewviewEl = document.createElement( 'div' ); // eslint-disable-line
prewviewEl.setAttribute( 'id', elId );
document.body.appendChild( prewviewEl ); // eslint-disable-line
let ticking = false;
const renderTransformation = () => {
if ( !ticking ) {
// eslint-disable-next-line
window.requestAnimationFrame( () => {
moveElement( element, prewviewEl );
ticking = false;
} );
ticking = true;
}
};
// Create scroll listener for following
window.addEventListener( 'resize', renderTransformation ); // eslint-disable-line
window.addEventListener( 'scroll', renderTransformation ); // eslint-disable-line
}
return prewviewEl;
}
function moveAndScaleElement( parent, element ) {
moveElement( parent, element );
// Scale parent element same as preview
const domRect = element.getBoundingClientRect();
// element.style.width = domRect.width + 'px';
parent.style.height = domRect.height + 'px';
}
function moveElement( parent, element ) {
const domRect = parent.getBoundingClientRect();
const left = window.scrollX + domRect.left; // eslint-disable-line
const top = window.scrollY + domRect.top; // eslint-disable-line
element.style.position = 'absolute';
element.style.left = left + 'px';
element.style.top = top + 'px';
element.style.zIndex = 'var(--ck-z-modal)';
element.style.pointerEvents = 'none';
}
// Simple MathJax 3 version check
export function isMathJaxVersion3( version ) {
return version && typeof version === 'string' && version.split( '.' ).length === 3 && version.split( '.' )[ 0 ] === '3';

View File

@ -6,12 +6,6 @@
flex-direction: row;
flex-wrap: nowrap;
& .ck.ck-math-preview {
/* Todo: calculate content size */
width: 234px;
height: 10em;
}
@mixin ck-media-phone {
flex-wrap: wrap;
@ -32,3 +26,8 @@
}
}
}
// Increase toolbar default z-index by one because math preview should be below of it
.ck.ck-toolbar-container {
z-index: calc(var(--ck-z-modal) + 2);
}