Fix writer and seperate schema

This commit is contained in:
Sauli Anto 2020-08-29 17:33:41 +03:00
parent 0ef44427ce
commit 7d0cd0187f
10 changed files with 101 additions and 88 deletions

View File

@ -6,6 +6,7 @@ module.exports = {
extends: 'ckeditor5', extends: 'ckeditor5',
globals: { globals: {
'MathJax': true, 'MathJax': true,
'katex': true 'katex': true,
'console': true
} }
}; };

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules/ node_modules/
build/ build/
package-lock.json package-lock.json
yarn.lock

View File

@ -28,7 +28,6 @@ This is TeX-based mathematical plugin for CKEditor 5. You can use it to insert,
- Have multiple input and output format - Have multiple input and output format
- Paste support - Paste support
- from plain text - from plain text
- from Microsoft Word
# Demos # Demos
[Classic editor with MathJax](https://jsfiddle.net/isaul32/qktj9h7x/) [Classic editor with MathJax](https://jsfiddle.net/isaul32/qktj9h7x/)
@ -42,11 +41,7 @@ This is TeX-based mathematical plugin for CKEditor 5. You can use it to insert,
## Requirements ## Requirements
- With CKEditor 5 v21.0.0, use ckeditor5-math@21.0.0 version - Use same version as CKEditor 5
- With CKEditor 5 v20.0.0, use ckeditor5-math@20.0.0 version
- With CKEditor 5 v19.0.0, use ckeditor5-math@19.0.0 version
- With CKEditor 5 v18.0.0, use ckeditor5-math@18.0.0 version
- With CKEditor 5 v17.0.0, use ckeditor5-math@17.0.1 version
If you get duplicated modules error, you have mismatching versions in your editor build package.json. If you get duplicated modules error, you have mismatching versions in your editor build package.json.
@ -176,7 +171,3 @@ Replace ckeditor5-core with git version
Run test suite Run test suite
`npm run test` `npm run test`
## Todo
- MathML input and output when using MathJax version 3
- Support multiple equations when pasting as plain text

View File

@ -1,37 +1,38 @@
{ {
"name": "ckeditor5-math", "name": "ckeditor5-math",
"version": "21.0.0", "version": "22.0.0",
"description": "Math feature for CKEditor 5.", "description": "Math feature for CKEditor 5.",
"keywords": [ "keywords": [
"ckeditor", "ckeditor",
"ckeditor5", "ckeditor5",
"ckeditor 5", "ckeditor 5",
"ckeditor5-feature", "ckeditor5-feature",
"ckeditor5-plugin" "ckeditor5-plugin",
"ckeditor5-math"
], ],
"dependencies": { "dependencies": {
"@ckeditor/ckeditor5-clipboard": "^21.0.0", "@ckeditor/ckeditor5-clipboard": "^22.0.0",
"@ckeditor/ckeditor5-core": "^21.0.0", "@ckeditor/ckeditor5-core": "^22.0.0",
"@ckeditor/ckeditor5-engine": "^21.0.0", "@ckeditor/ckeditor5-engine": "^22.0.0",
"@ckeditor/ckeditor5-ui": "^21.0.0", "@ckeditor/ckeditor5-ui": "^22.0.0",
"@ckeditor/ckeditor5-undo": "^21.0.0", "@ckeditor/ckeditor5-undo": "^22.0.0",
"@ckeditor/ckeditor5-utils": "^21.0.0", "@ckeditor/ckeditor5-utils": "^22.0.0",
"@ckeditor/ckeditor5-widget": "^21.0.0" "@ckeditor/ckeditor5-widget": "^22.0.0"
}, },
"devDependencies": { "devDependencies": {
"@ckeditor/ckeditor5-dev-tests": "^21.0.0", "@ckeditor/ckeditor5-dev-tests": "^22.0.0",
"@ckeditor/ckeditor5-editor-inline": "^21.0.0", "@ckeditor/ckeditor5-editor-inline": "^22.0.0",
"@ckeditor/ckeditor5-essentials": "^21.0.0", "@ckeditor/ckeditor5-essentials": "^22.0.0",
"@ckeditor/ckeditor5-paragraph": "^21.0.0", "@ckeditor/ckeditor5-paragraph": "^22.0.0",
"eslint": "^5.5.0", "eslint": "^7.1.0",
"eslint-config-ckeditor5": "^2.0.0", "eslint-config-ckeditor5": "^3.0.0",
"husky": "^1.3.1", "husky": "^4.2.5",
"lint-staged": "^7.0.0", "lint-staged": "^10.2.6",
"stylelint": "^11.1.1", "stylelint": "^13.5.0",
"stylelint-config-ckeditor5": "^1.0.0" "stylelint-config-ckeditor5": "^2.0.0"
}, },
"engines": { "engines": {
"node": ">=8.0.0", "node": ">=12.0.0",
"npm": ">=5.7.1" "npm": ">=5.7.1"
}, },
"author": "Sauli Anto", "author": "Sauli Anto",
@ -61,8 +62,10 @@
] ]
}, },
"eslintIgnore": [ "eslintIgnore": [
"src/lib/**", "node_modules/**",
"packages/**" "packages/*/node_modules/**",
"packages/*/build/**",
"packages/*/src/lib/**"
], ],
"husky": { "husky": {
"hooks": { "hooks": {

View File

@ -68,7 +68,7 @@ export default class AutoMath extends Plugin {
// 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' ) ) {
text += node.item.data; text += node.item.data;
} }
} }
@ -107,7 +107,7 @@ export default class AutoMath extends Plugin {
const params = Object.assign( extractDelimiters( text ), { const params = Object.assign( extractDelimiters( text ), {
type: mathConfig.outputType type: mathConfig.outputType
} ); } );
const mathElement = writer.createElement( 'mathtex', params ); const mathElement = writer.createElement( params.display ? 'mathtex-display' : 'mathtex-inline', params );
editor.model.insertContent( mathElement, insertPosition ); editor.model.insertContent( mathElement, insertPosition );

View File

@ -7,7 +7,7 @@ import AutoMath from './automath';
export default class Math extends Plugin { export default class Math extends Plugin {
static get requires() { static get requires() {
return [ MathEditing, MathUI, Widget, AutoMath ]; return [ MathEditing, MathUI, AutoMath, Widget ];
} }
static get pluginName() { static get pluginName() {

View File

@ -1,4 +1,5 @@
import Command from '@ckeditor/ckeditor5-core/src/command'; import Command from '@ckeditor/ckeditor5-core/src/command';
import { getSelectedMathModelWidget } from './utils'; import { getSelectedMathModelWidget } from './utils';
export default class MathCommand extends Command { export default class MathCommand extends Command {
@ -9,17 +10,18 @@ export default class MathCommand extends Command {
model.change( writer => { model.change( writer => {
let mathtex; let mathtex;
if ( selectedElement && selectedElement.is( 'mathtex' ) ) { if ( selectedElement && ( selectedElement.is( 'element', 'mathtex-inline' ) ||
selectedElement.is( 'element', 'mathtex-display' ) ) ) {
// Update selected element // Update selected element
const typeAttr = selectedElement.getAttribute( 'type' ); const typeAttr = selectedElement.getAttribute( 'type' );
// Use already set type if found and is not forced // Use already set type if found and is not forced
const type = forceOutputType ? outputType : typeAttr || outputType; const type = forceOutputType ? outputType : typeAttr || outputType;
mathtex = writer.createElement( 'mathtex', { equation, type, display } ); mathtex = writer.createElement( display ? 'mathtex-display' : 'mathtex-inline', { equation, type, display } );
} else { } else {
// Create new model element // Create new model element
mathtex = writer.createElement( 'mathtex', { equation, type: outputType, display } ); mathtex = writer.createElement( display ? 'mathtex-display' : 'mathtex-inline', { equation, type: outputType, display } );
} }
model.insertContent( mathtex ); model.insertContent( mathtex );
writer.setSelection( mathtex, 'on' ); writer.setSelection( mathtex, 'on' );
@ -29,9 +31,10 @@ export default class MathCommand extends Command {
refresh() { refresh() {
const model = this.editor.model; const model = this.editor.model;
const selection = model.document.selection; const selection = model.document.selection;
const selectedElement = selection.getSelectedElement();
const isAllowed = model.schema.checkChild( selection.focus.parent, 'mathtex' ); this.isEnabled = selectedElement === null || ( selectedElement.is( 'element', 'mathtex-inline' ) ||
this.isEnabled = isAllowed; selectedElement.is( 'element', 'mathtex-display' ) );
const selectedEquation = getSelectedMathModelWidget( selection ); const selectedEquation = getSelectedMathModelWidget( selection );
this.value = selectedEquation ? selectedEquation.getAttribute( 'equation' ) : null; this.value = selectedEquation ? selectedEquation.getAttribute( 'equation' ) : null;

View File

@ -36,13 +36,19 @@ export default class MathEditing extends Plugin {
_defineSchema() { _defineSchema() {
const schema = this.editor.model.schema; const schema = this.editor.model.schema;
schema.register( 'mathtex-inline', {
schema.register( 'mathtex', {
allowWhere: '$text', allowWhere: '$text',
isInline: true, isInline: true,
isObject: true, isObject: true,
allowAttributes: [ 'equation', 'type', 'display' ] allowAttributes: [ 'equation', 'type', 'display' ]
} ); } );
schema.register( 'mathtex-display', {
allowWhere: '$block',
isInline: false,
isObject: true,
allowAttributes: [ 'equation', 'type', 'display' ]
} );
} }
_defineConverters() { _defineConverters() {
@ -59,9 +65,9 @@ export default class MathEditing extends Plugin {
type: 'math/tex' type: 'math/tex'
} }
}, },
model: ( viewElement, modelWriter ) => { model: ( viewElement, { writer } ) => {
const equation = viewElement.getChild( 0 ).data.trim(); const equation = viewElement.getChild( 0 ).data.trim();
return modelWriter.createElement( 'mathtex', { return writer.createElement( 'mathtex-inline', {
equation, equation,
type: mathConfig.forceOutputType ? mathConfig.outputType : 'script', type: mathConfig.forceOutputType ? mathConfig.outputType : 'script',
display: false display: false
@ -76,9 +82,9 @@ export default class MathEditing extends Plugin {
type: 'math/tex; mode=display' type: 'math/tex; mode=display'
} }
}, },
model: ( viewElement, modelWriter ) => { model: ( viewElement, { writer } ) => {
const equation = viewElement.getChild( 0 ).data.trim(); const equation = viewElement.getChild( 0 ).data.trim();
return modelWriter.createElement( 'mathtex', { return writer.createElement( 'mathtex-display', {
equation, equation,
type: mathConfig.forceOutputType ? mathConfig.outputType : 'script', type: mathConfig.forceOutputType ? mathConfig.outputType : 'script',
display: true display: true
@ -91,46 +97,58 @@ export default class MathEditing extends Plugin {
name: 'span', name: 'span',
classes: [ 'math-tex' ] classes: [ 'math-tex' ]
}, },
model: ( viewElement, modelWriter ) => { model: ( viewElement, { writer } ) => {
const equation = viewElement.getChild( 0 ).data.trim(); const equation = viewElement.getChild( 0 ).data.trim();
const params = Object.assign( extractDelimiters( equation ), { const params = Object.assign( extractDelimiters( equation ), {
type: mathConfig.forceOutputType ? mathConfig.outputType : 'span' type: mathConfig.forceOutputType ? mathConfig.outputType : 'span'
} ); } );
return modelWriter.createElement( 'mathtex', params ); return writer.createElement( params.display ? 'mathtex-display' : 'mathtex-inline', params );
} }
} ); } );
// Model -> View (element) // Model -> View (element)
conversion.for( 'editingDowncast' ).elementToElement( { conversion.for( 'editingDowncast' )
model: 'mathtex', .elementToElement( {
view: ( modelItem, viewWriter ) => { model: 'mathtex-inline',
const widgetElement = createMathtexEditingView( modelItem, viewWriter ); view: ( modelItem, { writer } ) => {
return toWidget( widgetElement, viewWriter ); const widgetElement = createMathtexEditingView( modelItem, writer );
} return toWidget( widgetElement, writer, 'span' );
} ); }
} ).elementToElement( {
model: 'mathtex-display',
view: ( modelItem, { writer } ) => {
const widgetElement = createMathtexEditingView( modelItem, writer );
return toWidget( widgetElement, writer, 'div' );
}
} );
// Model -> Data // Model -> Data
conversion.for( 'dataDowncast' ).elementToElement( { conversion.for( 'dataDowncast' )
model: 'mathtex', .elementToElement( {
view: createMathtexView model: 'mathtex-inline',
} ); view: createMathtexView
} )
.elementToElement( {
model: 'mathtex-display',
view: createMathtexView
} );
// Create view for editor // Create view for editor
function createMathtexEditingView( modelItem, viewWriter ) { function createMathtexEditingView( modelItem, writer ) {
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: 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' );
const mathtexView = viewWriter.createContainerElement( 'span', { const mathtexView = writer.createContainerElement( display ? 'div' : 'span', {
style: styles, style: styles,
class: classes class: classes
} ); } );
const uiElement = viewWriter.createUIElement( 'div', null, function( domDocument ) { const uiElement = writer.createUIElement( 'div', null, function( domDocument ) {
const domElement = this.toDomElement( domDocument ); const domElement = this.toDomElement( domDocument );
renderEquation( equation, domElement, mathConfig.engine, display, false ); renderEquation( equation, domElement, mathConfig.engine, display, false );
@ -138,35 +156,35 @@ export default class MathEditing extends Plugin {
return domElement; return domElement;
} ); } );
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), uiElement ); writer.insert( writer.createPositionAt( mathtexView, 0 ), uiElement );
return mathtexView; return mathtexView;
} }
// Create view for data // Create view for data
function createMathtexView( modelItem, viewWriter ) { function createMathtexView( modelItem, { writer } ) {
const equation = modelItem.getAttribute( 'equation' ); const equation = modelItem.getAttribute( 'equation' );
const type = modelItem.getAttribute( 'type' ); const type = modelItem.getAttribute( 'type' );
const display = modelItem.getAttribute( 'display' ); const display = modelItem.getAttribute( 'display' );
if ( type === 'span' ) { if ( type === 'span' ) {
const mathtexView = viewWriter.createContainerElement( 'span', { const mathtexView = writer.createContainerElement( 'span', {
class: 'math-tex' class: 'math-tex'
} ); } );
if ( display ) { if ( display ) {
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), viewWriter.createText( '\\[' + equation + '\\]' ) ); writer.insert( writer.createPositionAt( mathtexView, 0 ), writer.createText( '\\[' + equation + '\\]' ) );
} else { } else {
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), viewWriter.createText( '\\(' + equation + '\\)' ) ); writer.insert( writer.createPositionAt( mathtexView, 0 ), writer.createText( '\\(' + equation + '\\)' ) );
} }
return mathtexView; return mathtexView;
} else { } else {
const mathtexView = viewWriter.createContainerElement( 'script', { const mathtexView = writer.createContainerElement( 'script', {
type: display ? 'math/tex; mode=display' : 'math/tex' type: display ? 'math/tex; mode=display' : 'math/tex'
} ); } );
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), viewWriter.createText( equation ) ); writer.insert( writer.createPositionAt( mathtexView, 0 ), writer.createText( equation ) );
return mathtexView; return mathtexView;
} }

View File

@ -1,11 +1,9 @@
/* globals MathJax, katex, console */
import global from '@ckeditor/ckeditor5-utils/src/dom/global'; import global from '@ckeditor/ckeditor5-utils/src/dom/global';
export function getSelectedMathModelWidget( selection ) { export function getSelectedMathModelWidget( selection ) {
const selectedElement = selection.getSelectedElement(); const selectedElement = selection.getSelectedElement();
if ( selectedElement && selectedElement.is( 'mathtex' ) ) { if ( selectedElement && ( selectedElement.is( 'element', 'mathtex-inline' ) || selectedElement.is( 'element', 'mathtex-display' ) ) ) {
return selectedElement; return selectedElement;
} }

View File

@ -1,24 +1,22 @@
@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";
.ck.ck-math-form { .ck.ck-math-form {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
flex-direction: row; flex-direction: row;
flex-wrap: nowrap; flex-wrap: nowrap;
@mixin ck-media-phone { @media screen and (max-width: 600px) {
flex-wrap: wrap; flex-wrap: wrap;
& .ck-math-view { & .ck-math-view {
flex-basis: 100%; flex-basis: 100%;
& .ck-labeled-input { & .ck-labeled-input {
flex-basis: 100%; flex-basis: 100%;
} }
& .ck-label { & .ck-label {
flex-basis: 100%; flex-basis: 100%;
} }
} }
& .ck-button { & .ck-button {
@ -27,7 +25,7 @@
} }
} }
// Increase toolbar default z-index by one because math preview should be below of it /* Increase toolbar default z-index by one because math preview should be below of it */
.ck.ck-toolbar-container { .ck.ck-toolbar-container {
z-index: calc(var(--ck-z-modal) + 2); z-index: calc(var(--ck-z-modal) + 2);
} }