mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-30 03:32:26 +08:00
Refactor code
This commit is contained in:
parent
5011fe40b0
commit
f89affbc3f
@ -3,5 +3,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
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
|
### Available typesetting engines
|
||||||
__MathJax__
|
__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
|
- Use __\\( \\)__ delimiters for inline and __\\[ \\]__ delimiters for display
|
||||||
|
|
||||||
__KaTeX__
|
__KaTeX__
|
||||||
|
@ -4,7 +4,7 @@ import Undo from '@ckeditor/ckeditor5-undo/src/undo';
|
|||||||
import LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange';
|
import LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange';
|
||||||
import LivePosition from '@ckeditor/ckeditor5-engine/src/model/liveposition';
|
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 {
|
export default class AutoMath extends Plugin {
|
||||||
static get requires() {
|
static get requires() {
|
||||||
@ -66,19 +66,19 @@ export default class AutoMath extends Plugin {
|
|||||||
const equationRange = new LiveRange( leftPosition, rightPosition );
|
const equationRange = new LiveRange( leftPosition, rightPosition );
|
||||||
const walker = equationRange.getWalker( { ignoreElementEnd: true } );
|
const walker = equationRange.getWalker( { ignoreElementEnd: true } );
|
||||||
|
|
||||||
let equation = '';
|
let text = '';
|
||||||
|
|
||||||
// Get equation text
|
// Get equation text
|
||||||
for ( const node of walker ) {
|
for ( const node of walker ) {
|
||||||
if ( node.item.is( 'textProxy' ) ) {
|
if ( node.item.is( 'textProxy' ) ) {
|
||||||
equation += node.item.data;
|
text += node.item.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
equation = equation.trim();
|
text = text.trim();
|
||||||
|
|
||||||
// Check if equation
|
// Skip if don't have delimiters
|
||||||
if ( !equation.match( EQUATION_REGEXP ) ) {
|
if ( !hasDelimiters( text ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ export default class AutoMath extends Plugin {
|
|||||||
|
|
||||||
editor.model.change( writer => {
|
editor.model.change( writer => {
|
||||||
const params = {
|
const params = {
|
||||||
...removeDelimiters( equation ),
|
...extractDelimiters( text ),
|
||||||
type: mathConfig.outputType,
|
type: mathConfig.outputType,
|
||||||
};
|
};
|
||||||
const mathElement = writer.createElement( 'mathtex', params );
|
const mathElement = writer.createElement( 'mathtex', params );
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
||||||
|
|
||||||
import { toWidget } from '@ckeditor/ckeditor5-widget/src/utils';
|
import { toWidget } from '@ckeditor/ckeditor5-widget/src/utils';
|
||||||
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
|
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
|
||||||
|
|
||||||
import MathCommand from './mathcommand';
|
import MathCommand from './mathcommand';
|
||||||
|
|
||||||
import { defaultConfig, renderEquation, removeDelimiters } from './utils';
|
import { defaultConfig, renderEquation, extractDelimiters } from './utils';
|
||||||
|
|
||||||
export default class MathEditing extends Plugin {
|
export default class MathEditing extends Plugin {
|
||||||
static get requires() {
|
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>)
|
// CKEditor 4 way (e.g. <span class="math-tex">\( \sqrt{\frac{a}{b}} \)</span>)
|
||||||
.elementToElement( {
|
.elementToElement( {
|
||||||
view: {
|
view: {
|
||||||
@ -108,7 +87,7 @@ export default class MathEditing extends Plugin {
|
|||||||
const equation = viewElement.getChild( 0 ).data.trim();
|
const equation = viewElement.getChild( 0 ).data.trim();
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
...removeDelimiters( equation ),
|
...extractDelimiters( equation ),
|
||||||
type: mathConfig.forceOutputType ? mathConfig.outputType : 'span'
|
type: mathConfig.forceOutputType ? mathConfig.outputType : 'span'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -136,7 +115,7 @@ export default class MathEditing extends Plugin {
|
|||||||
const equation = modelItem.getAttribute( 'equation' );
|
const equation = modelItem.getAttribute( 'equation' );
|
||||||
const display = modelItem.getAttribute( 'display' );
|
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' );
|
const classes = 'ck-math-tex ' + ( display ? 'ck-math-tex-display' : 'ck-math-tex-inline' );
|
||||||
|
|
||||||
// CKEngine render multiple times if using span instead of div
|
// CKEngine render multiple times if using span instead of div
|
||||||
@ -177,19 +156,7 @@ export default class MathEditing extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return mathtexView;
|
return mathtexView;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
/*
|
|
||||||
else if ( type === 'math' ) {
|
|
||||||
const mathtexView = viewWriter.createContainerElement( 'math', {
|
|
||||||
display: display ? 'block' : 'inline',
|
|
||||||
alttex: equation
|
|
||||||
} );
|
|
||||||
// Todo: Implement output conversion
|
|
||||||
return mathtexView;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
const mathtexView = viewWriter.createContainerElement( 'script', {
|
const mathtexView = viewWriter.createContainerElement( 'script', {
|
||||||
type: display ? 'math/tex; mode=display' : 'math/tex'
|
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 submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';
|
||||||
|
|
||||||
import { removeDelimiters, EQUATION_REGEXP } from '../utils';
|
import { extractDelimiters, hasDelimiters } from '../utils';
|
||||||
|
|
||||||
import MathView from './mathview';
|
import MathView from './mathview';
|
||||||
|
|
||||||
@ -33,8 +33,9 @@ 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
|
// 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
|
// Display button
|
||||||
this.displayButtonView = this._createDisplayButton();
|
this.displayButtonView = this._createDisplayButton();
|
||||||
@ -166,9 +167,9 @@ export default class MainFormView extends View {
|
|||||||
const equationInput = inputView.element.value.trim();
|
const equationInput = inputView.element.value.trim();
|
||||||
|
|
||||||
// If input has delimiters
|
// If input has delimiters
|
||||||
if ( equationInput.match( EQUATION_REGEXP ) ) {
|
if ( hasDelimiters( equationInput ) ) {
|
||||||
// Get equation without delimiters
|
// Get equation without delimiters
|
||||||
const params = removeDelimiters( equationInput );
|
const params = extractDelimiters( equationInput );
|
||||||
|
|
||||||
// Remove delimiters from input field
|
// Remove delimiters from input field
|
||||||
inputView.element.value = params.equation;
|
inputView.element.value = params.equation;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import View from '@ckeditor/ckeditor5-ui/src/view';
|
import View from '@ckeditor/ckeditor5-ui/src/view';
|
||||||
|
|
||||||
import { renderEquation } from '../utils';
|
import { renderEquation } from '../utils';
|
||||||
|
|
||||||
export default class MathView extends View {
|
export default class MathView extends View {
|
||||||
@ -15,7 +16,7 @@ export default class MathView extends View {
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
this.setTemplate( {
|
this.setTemplate( {
|
||||||
tag: 'div',
|
tag: 'iframe',
|
||||||
attributes: {
|
attributes: {
|
||||||
class: [
|
class: [
|
||||||
'ck',
|
'ck',
|
||||||
@ -26,7 +27,43 @@ export default class MathView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateMath() {
|
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() {
|
render() {
|
||||||
|
115
src/utils.js
115
src/utils.js
@ -1,62 +1,9 @@
|
|||||||
export const EQUATION_REGEXP = /^(\\\[.*?\\\]|\\\(.*?\\\))$/;
|
|
||||||
|
|
||||||
export const defaultConfig = {
|
export const defaultConfig = {
|
||||||
engine: 'mathjax',
|
engine: 'mathjax',
|
||||||
outputType: 'script',
|
outputType: 'script',
|
||||||
forceOutputType: false
|
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 ) {
|
export function getSelectedMathModelWidget( selection ) {
|
||||||
const selectedElement = selection.getSelectedElement();
|
const selectedElement = selection.getSelectedElement();
|
||||||
|
|
||||||
@ -67,8 +14,66 @@ export function getSelectedMathModelWidget( selection ) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove delimiters and figure display mode for the model
|
export function renderEquation( equation, element, engine = 'katex', display = false ) {
|
||||||
export function removeDelimiters( equation ) {
|
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();
|
equation = equation.trim();
|
||||||
|
|
||||||
// Remove delimiters (e.g. \( \) or \[ \])
|
// Remove delimiters (e.g. \( \) or \[ \])
|
||||||
|
@ -7,13 +7,9 @@
|
|||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
& .ck.ck-math-preview {
|
& .ck.ck-math-preview {
|
||||||
user-select: none;
|
// Todo: calculate content size
|
||||||
}
|
width: 234px;
|
||||||
|
height: 10em;
|
||||||
/* FIXME: mathjax isn't working with .ck.ck-reset_all * without this fix*/
|
|
||||||
& .ck.ck-math-preview * {
|
|
||||||
vertical-align: initial;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin ck-media-phone {
|
@mixin ck-media-phone {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user