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' ) ...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.mathInputView.bind( 'value' ).to( mathCommand, 'value' );
formView.displayButtonView.bind( 'isOn' ).to( mathCommand, 'display' ); formView.displayButtonView.bind( 'isOn' ).to( mathCommand, 'display' );
@ -106,6 +106,13 @@ export default class MathUI extends Plugin {
this._form.mathInputView.select(); 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.equation = mathCommand.value || '';
this._form.displayButtonView.isOn = mathCommand.display || false; this._form.displayButtonView.isOn = mathCommand.display || false;
} }
@ -141,6 +148,13 @@ export default class MathUI extends Plugin {
this._balloon.remove( this._form ); 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(); this.editor.editing.view.focus();
} }
} }

View File

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

View File

@ -16,7 +16,7 @@ export default class MathView extends View {
} ); } );
this.setTemplate( { this.setTemplate( {
tag: 'iframe', tag: 'div',
attributes: { attributes: {
class: [ class: [
'ck', 'ck',
@ -29,40 +29,7 @@ export default class MathView extends View {
updateMath() { updateMath() {
const el = this.element; const el = this.element;
if ( el ) { if ( el ) {
// Fixme renderEquation( this.value, el, this.engine, this.display, true );
// 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 );
} }
} }

View File

@ -1,7 +1,8 @@
export const defaultConfig = { export const defaultConfig = {
engine: 'mathjax', engine: 'mathjax',
outputType: 'script', outputType: 'script',
forceOutputType: false forceOutputType: false,
enablePreview: true
}; };
export function getSelectedMathModelWidget( selection ) { export function getSelectedMathModelWidget( selection ) {
@ -14,47 +15,30 @@ export function getSelectedMathModelWidget( selection ) {
return null; 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 ( engine === 'mathjax' && typeof MathJax !== 'undefined' ) {
if ( isMathJaxVersion3( MathJax.version ) ) { if ( isMathJaxVersion3( MathJax.version ) ) {
const options = MathJax.getMetricsFor( element, display ); selectRenderMode( element, previewHack, el => {
let promiseFunction = undefined; renderMathJax3( equation, el, display, () => {
if ( typeof MathJax.tex2chtmlPromise !== 'undefined' ) { if ( previewHack ) {
promiseFunction = MathJax.tex2chtmlPromise; moveAndScaleElement( element, el );
} 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();
} ); } );
} } );
} else { } else {
// Fixme: MathJax typesetting cause occasionally math processing error without asynchronous call selectRenderMode( element, previewHack, el => {
// eslint-disable-next-line renderMathJax2( equation, el, display );
setTimeout( () => {
if ( display ) {
element.innerHTML = '\\[' + equation + '\\]';
} else {
element.innerHTML = '\\(' + equation + '\\)';
}
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, element ] ); // eslint-disable-line
} ); } );
} }
} else if ( engine === 'katex' && typeof katex !== 'undefined' ) { } else if ( engine === 'katex' && typeof katex !== 'undefined' ) {
katex.render( equation, element, { selectRenderMode( element, previewHack, el => {
throwOnError: false, katex.render( equation, el, {
displayMode: display throwOnError: false,
displayMode: display
} );
} ); } );
} else if ( typeof engine === 'function' ) { } else if ( typeof engine === 'function' ) {
engine( equation, element, display ); engine( equation, element, display, previewHack );
} else { } else {
element.innerHTML = equation; element.innerHTML = equation;
// eslint-disable-next-line // 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 // Simple MathJax 3 version check
export function isMathJaxVersion3( version ) { export function isMathJaxVersion3( version ) {
return version && typeof version === 'string' && version.split( '.' ).length === 3 && version.split( '.' )[ 0 ] === '3'; return version && typeof version === 'string' && version.split( '.' ).length === 3 && version.split( '.' )[ 0 ] === '3';

View File

@ -6,12 +6,6 @@
flex-direction: row; flex-direction: row;
flex-wrap: nowrap; flex-wrap: nowrap;
& .ck.ck-math-preview {
/* Todo: calculate content size */
width: 234px;
height: 10em;
}
@mixin ck-media-phone { @mixin ck-media-phone {
flex-wrap: wrap; 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);
}