mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-29 19:12:27 +08:00
Refactor code
This commit is contained in:
parent
5011fe40b0
commit
f89affbc3f
@ -3,5 +3,9 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
extends: 'ckeditor5'
|
||||
extends: 'ckeditor5',
|
||||
globals: {
|
||||
'MathJax': true,
|
||||
'katex': true
|
||||
}
|
||||
};
|
@ -54,7 +54,7 @@ Styles requires PostCSS like offical CKEditor plugins.
|
||||
|
||||
### Available typesetting engines
|
||||
__MathJax__
|
||||
- Tested by using version __2.7.5__ and __TeX-MML-AM_HTMLorMML__ configuration. It works also with version __3.0.0__ or newer!
|
||||
- Tested by using version __2.7.5__ and __TeX-MML-AM_HTMLorMML__ configuration. It has also experimental (__CHTML__, __SVG__) support for __3.0.0__ or newer version.
|
||||
- Use __\\( \\)__ delimiters for inline and __\\[ \\]__ delimiters for display
|
||||
|
||||
__KaTeX__
|
||||
|
@ -4,7 +4,7 @@ import Undo from '@ckeditor/ckeditor5-undo/src/undo';
|
||||
import LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange';
|
||||
import LivePosition from '@ckeditor/ckeditor5-engine/src/model/liveposition';
|
||||
|
||||
import { defaultConfig, removeDelimiters, EQUATION_REGEXP } from './utils';
|
||||
import { defaultConfig, extractDelimiters, hasDelimiters } from './utils';
|
||||
|
||||
export default class AutoMath extends Plugin {
|
||||
static get requires() {
|
||||
@ -66,19 +66,19 @@ export default class AutoMath extends Plugin {
|
||||
const equationRange = new LiveRange( leftPosition, rightPosition );
|
||||
const walker = equationRange.getWalker( { ignoreElementEnd: true } );
|
||||
|
||||
let equation = '';
|
||||
let text = '';
|
||||
|
||||
// Get equation text
|
||||
for ( const node of walker ) {
|
||||
if ( node.item.is( 'textProxy' ) ) {
|
||||
equation += node.item.data;
|
||||
text += node.item.data;
|
||||
}
|
||||
}
|
||||
|
||||
equation = equation.trim();
|
||||
text = text.trim();
|
||||
|
||||
// Check if equation
|
||||
if ( !equation.match( EQUATION_REGEXP ) ) {
|
||||
// Skip if don't have delimiters
|
||||
if ( !hasDelimiters( text ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ export default class AutoMath extends Plugin {
|
||||
|
||||
editor.model.change( writer => {
|
||||
const params = {
|
||||
...removeDelimiters( equation ),
|
||||
...extractDelimiters( text ),
|
||||
type: mathConfig.outputType,
|
||||
};
|
||||
const mathElement = writer.createElement( 'mathtex', params );
|
||||
|
@ -1,11 +1,10 @@
|
||||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
||||
|
||||
import { toWidget } from '@ckeditor/ckeditor5-widget/src/utils';
|
||||
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
|
||||
|
||||
import MathCommand from './mathcommand';
|
||||
|
||||
import { defaultConfig, renderEquation, removeDelimiters } from './utils';
|
||||
import { defaultConfig, renderEquation, extractDelimiters } from './utils';
|
||||
|
||||
export default class MathEditing extends Plugin {
|
||||
static get requires() {
|
||||
@ -78,26 +77,6 @@ export default class MathEditing extends Plugin {
|
||||
} );
|
||||
}
|
||||
} )
|
||||
// Todo: Implement input conversion
|
||||
/*
|
||||
// MathML (e.g. <math type="math/tex; mode=display" alttext="\sqrt{\frac{a}{b}}">...</script>)
|
||||
.elementToElement( {
|
||||
view: {
|
||||
name: 'math',
|
||||
},
|
||||
model: ( viewElement, modelWriter ) => {
|
||||
const equation = viewElement.getAttribute( 'alttext' );
|
||||
const display = viewElement.getAttribute( 'display' );
|
||||
if ( equation ) {
|
||||
return modelWriter.createElement( 'mathtex', {
|
||||
equation,
|
||||
type: mathConfig.forceOutputType ? mathConfig.outputType : 'math',
|
||||
display: display === 'block' ? true : false
|
||||
} );
|
||||
}
|
||||
}
|
||||
} )
|
||||
*/
|
||||
// CKEditor 4 way (e.g. <span class="math-tex">\( \sqrt{\frac{a}{b}} \)</span>)
|
||||
.elementToElement( {
|
||||
view: {
|
||||
@ -108,7 +87,7 @@ export default class MathEditing extends Plugin {
|
||||
const equation = viewElement.getChild( 0 ).data.trim();
|
||||
|
||||
const params = {
|
||||
...removeDelimiters( equation ),
|
||||
...extractDelimiters( equation ),
|
||||
type: mathConfig.forceOutputType ? mathConfig.outputType : 'span'
|
||||
};
|
||||
|
||||
@ -136,7 +115,7 @@ export default class MathEditing extends Plugin {
|
||||
const equation = modelItem.getAttribute( 'equation' );
|
||||
const display = modelItem.getAttribute( 'display' );
|
||||
|
||||
const styles = 'user-select: none; ' + ( display ? 'display: block;' : 'display: inline-block;' );
|
||||
const styles = 'user-select: none; ' + ( display ? '' : 'display: inline-block;' );
|
||||
const classes = 'ck-math-tex ' + ( display ? 'ck-math-tex-display' : 'ck-math-tex-inline' );
|
||||
|
||||
// CKEngine render multiple times if using span instead of div
|
||||
@ -177,19 +156,7 @@ export default class MathEditing extends Plugin {
|
||||
}
|
||||
|
||||
return mathtexView;
|
||||
}
|
||||
|
||||
/*
|
||||
else if ( type === 'math' ) {
|
||||
const mathtexView = viewWriter.createContainerElement( 'math', {
|
||||
display: display ? 'block' : 'inline',
|
||||
alttex: equation
|
||||
} );
|
||||
// Todo: Implement output conversion
|
||||
return mathtexView;
|
||||
}
|
||||
*/
|
||||
else {
|
||||
} else {
|
||||
const mathtexView = viewWriter.createContainerElement( 'script', {
|
||||
type: display ? 'math/tex; mode=display' : 'math/tex'
|
||||
} );
|
||||
|
@ -15,7 +15,7 @@ import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';
|
||||
|
||||
import submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';
|
||||
|
||||
import { removeDelimiters, EQUATION_REGEXP } from '../utils';
|
||||
import { extractDelimiters, hasDelimiters } from '../utils';
|
||||
|
||||
import MathView from './mathview';
|
||||
|
||||
@ -33,8 +33,9 @@ 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';
|
||||
this.previewEnabled = engine !== 'katex' || true;
|
||||
|
||||
// Display button
|
||||
this.displayButtonView = this._createDisplayButton();
|
||||
@ -166,9 +167,9 @@ export default class MainFormView extends View {
|
||||
const equationInput = inputView.element.value.trim();
|
||||
|
||||
// If input has delimiters
|
||||
if ( equationInput.match( EQUATION_REGEXP ) ) {
|
||||
if ( hasDelimiters( equationInput ) ) {
|
||||
// Get equation without delimiters
|
||||
const params = removeDelimiters( equationInput );
|
||||
const params = extractDelimiters( equationInput );
|
||||
|
||||
// Remove delimiters from input field
|
||||
inputView.element.value = params.equation;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import View from '@ckeditor/ckeditor5-ui/src/view';
|
||||
|
||||
import { renderEquation } from '../utils';
|
||||
|
||||
export default class MathView extends View {
|
||||
@ -15,7 +16,7 @@ export default class MathView extends View {
|
||||
} );
|
||||
|
||||
this.setTemplate( {
|
||||
tag: 'div',
|
||||
tag: 'iframe',
|
||||
attributes: {
|
||||
class: [
|
||||
'ck',
|
||||
@ -26,7 +27,43 @@ export default class MathView extends View {
|
||||
}
|
||||
|
||||
updateMath() {
|
||||
renderEquation( this.value, this.element, this.engine, this.display );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
115
src/utils.js
115
src/utils.js
@ -1,62 +1,9 @@
|
||||
export const EQUATION_REGEXP = /^(\\\[.*?\\\]|\\\(.*?\\\))$/;
|
||||
|
||||
export const defaultConfig = {
|
||||
engine: 'mathjax',
|
||||
outputType: 'script',
|
||||
forceOutputType: false
|
||||
};
|
||||
|
||||
export function renderEquation( equation, element, engine = 'katex', display = false ) {
|
||||
if ( !element ) {
|
||||
return;
|
||||
}
|
||||
/* eslint-disable */
|
||||
if ( engine === 'mathjax' && typeof MathJax !== 'undefined' ) {
|
||||
const version = MathJax.version;
|
||||
// If major version is 3
|
||||
if ( isMathJaxVersion3( version ) ) {
|
||||
const options = MathJax.getMetricsFor( element );
|
||||
|
||||
MathJax.texReset();
|
||||
MathJax.tex2chtmlPromise( equation, options ).then( node => {
|
||||
if ( element.firstChild ) {
|
||||
element.firstChild.replaceWith( node );
|
||||
} else {
|
||||
element.appendChild( node );
|
||||
}
|
||||
MathJax.startup.document.clear();
|
||||
MathJax.startup.document.updateDocument();
|
||||
} );
|
||||
} else {
|
||||
// Fixme: MathJax typesetting cause occasionally math processing error without timeout
|
||||
setTimeout( () => {
|
||||
if ( display ) {
|
||||
element.innerHTML = '\\[' + equation + '\\]';
|
||||
} else {
|
||||
element.innerHTML = '\\(' + equation + '\\)';
|
||||
}
|
||||
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, element ] );
|
||||
}, 50);
|
||||
}
|
||||
} else if ( engine === 'katex' && typeof katex !== 'undefined' ) {
|
||||
katex.render( equation, element, {
|
||||
throwOnError: false,
|
||||
displayMode: display
|
||||
} );
|
||||
} else if ( typeof engine === 'function' ) {
|
||||
engine( equation, element, display );
|
||||
} else {
|
||||
element.innerHTML = equation;
|
||||
console.warn( `math-tex-typesetting-missing: Missing the mathematical typesetting engine (${engine}) for tex.` );
|
||||
}
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
// Simple MathJax 3 version check
|
||||
export function isMathJaxVersion3( version ) {
|
||||
return version && typeof version === 'string' && version.split( '.' ).length === 3 && version.split( '.' )[ 0 ] === '3';
|
||||
}
|
||||
|
||||
export function getSelectedMathModelWidget( selection ) {
|
||||
const selectedElement = selection.getSelectedElement();
|
||||
|
||||
@ -67,8 +14,66 @@ export function getSelectedMathModelWidget( selection ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Remove delimiters and figure display mode for the model
|
||||
export function removeDelimiters( equation ) {
|
||||
export function renderEquation( equation, element, engine = 'katex', display = 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 );
|
||||
}
|
||||
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
|
||||
} );
|
||||
}
|
||||
} else if ( engine === 'katex' && typeof katex !== 'undefined' ) {
|
||||
katex.render( equation, element, {
|
||||
throwOnError: false,
|
||||
displayMode: display
|
||||
} );
|
||||
} else if ( typeof engine === 'function' ) {
|
||||
engine( equation, element, display );
|
||||
} else {
|
||||
element.innerHTML = equation;
|
||||
// eslint-disable-next-line
|
||||
console.warn( `math-tex-typesetting-missing: Missing the mathematical typesetting engine (${engine}) for tex.` );
|
||||
}
|
||||
}
|
||||
|
||||
// Simple MathJax 3 version check
|
||||
export function isMathJaxVersion3( version ) {
|
||||
return version && typeof version === 'string' && version.split( '.' ).length === 3 && version.split( '.' )[ 0 ] === '3';
|
||||
}
|
||||
|
||||
// Check if equation has delimiters
|
||||
export function hasDelimiters( text ) {
|
||||
return text.match( /^(\\\[.*?\\\]|\\\(.*?\\\))$/ );
|
||||
}
|
||||
|
||||
// Extract delimiters and figure display mode for the model
|
||||
export function extractDelimiters( equation ) {
|
||||
equation = equation.trim();
|
||||
|
||||
// Remove delimiters (e.g. \( \) or \[ \])
|
||||
|
@ -7,13 +7,9 @@
|
||||
flex-wrap: nowrap;
|
||||
|
||||
& .ck.ck-math-preview {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* FIXME: mathjax isn't working with .ck.ck-reset_all * without this fix*/
|
||||
& .ck.ck-math-preview * {
|
||||
vertical-align: initial;
|
||||
text-align: center;
|
||||
// Todo: calculate content size
|
||||
width: 234px;
|
||||
height: 10em;
|
||||
}
|
||||
|
||||
@mixin ck-media-phone {
|
||||
|
Loading…
x
Reference in New Issue
Block a user