Implement plugin

This commit is contained in:
Sauli Anto 2019-08-31 20:48:37 +03:00
commit 13a10dcfdd
16 changed files with 3813 additions and 0 deletions

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*]
indent_style = tab
tab_width = 4
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true

7
.eslintrc.js Normal file
View File

@ -0,0 +1,7 @@
/* eslint-env node */
'use strict';
module.exports = {
extends: 'ckeditor5'
};

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules/

5
LICENSE Normal file
View File

@ -0,0 +1,5 @@
Copyright 2019 isaul32
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

10
README.md Normal file
View File

@ -0,0 +1,10 @@
# ckeditor5-math
## Supported input and output formats
- <script type="math/tex">\sqrt{\frac{a}{b}}</script>
- <script type="math/tex; mode=display">\sqrt{\frac{a}{b}}</script>
- <span class="math-tex">\( \sqrt{\frac{a}{b}} \)</span>
- <span class="math-tex">\[ \sqrt{\frac{a}{b}} \]</span>
## Styles
- Styles requires PostCSS

3041
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

50
package.json Normal file
View File

@ -0,0 +1,50 @@
{
"name": "ckeditor5-math",
"version": "1.0.0",
"description": "Math feature for CKEditor 5.",
"keywords": [
"ckeditor",
"ckeditor5",
"ckeditor 5",
"ckeditor5-feature",
"ckeditor5-plugin"
],
"dependencies": {
"@ckeditor/ckeditor5-core": "^12.3.0",
"@ckeditor/ckeditor5-ui": "^14.0.0",
"@ckeditor/ckeditor5-utils": "^14.0.0"
},
"devDependencies": {
"@ckeditor/ckeditor5-editor-inline": "^12.3.0",
"@ckeditor/ckeditor5-essentials": "^11.0.5",
"eslint": "^5.5.0",
"eslint-config-ckeditor5": "^2.0.0",
"husky": "^1.3.1",
"lint-staged": "^7.0.0"
},
"engines": {
"node": ">=8.0.0",
"npm": ">=5.7.1"
},
"author": "isaul32",
"license": "ISC",
"files": [
"lang",
"src",
"theme"
],
"scripts": {
"lint": "eslint --quiet **/*.js",
"lint:fix": "eslint --quiet **/*.js --fix"
},
"lint-staged": {
"**/*.js": [
"eslint --quiet"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
}

15
src/math.js Normal file
View File

@ -0,0 +1,15 @@
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import Widget from '@ckeditor/ckeditor5-widget/src/widget';
import MathUI from './mathui';
import MathEditing from './mathediting';
export default class Math extends Plugin {
static get requires() {
return [ MathEditing, MathUI, Widget ];
}
static get pluginName() {
return 'Math';
}
}

36
src/mathcommand.js Normal file
View File

@ -0,0 +1,36 @@
import Command from '@ckeditor/ckeditor5-core/src/command';
import { getSelectedMathModelWidget } from './utils';
export default class MathCommand extends Command {
execute( equation ) {
const model = this.editor.model;
const selection = model.document.selection;
const selectedElement = selection.getSelectedElement();
model.change( writer => {
let mathtex;
if ( selectedElement && selectedElement.is( 'mathtex' ) ) {
// Update selected element
const mode = selectedElement.getAttribute( 'mode' );
const display = selectedElement.getAttribute( 'display' );
mathtex = writer.createElement( 'mathtex', { equation, mode, display } );
} else {
// Create new model element
mathtex = writer.createElement( 'mathtex', { equation, mode: 'script', display: true } );
}
model.insertContent( mathtex );
writer.setSelection( mathtex, 'on' );
} );
}
refresh() {
const model = this.editor.model;
const selection = model.document.selection;
const isAllowed = model.schema.checkChild( selection.focus.parent, 'mathtex' );
this.isEnabled = isAllowed;
const selectedEquation = getSelectedMathModelWidget( selection );
this.value = selectedEquation ? selectedEquation.getAttribute( 'equation' ) : null;
}
}

160
src/mathediting.js Normal file
View File

@ -0,0 +1,160 @@
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 { renderEquation } from './utils';
export default class MathEditing extends Plugin {
static get requires() {
return [ Widget ];
}
static get pluginName() {
return 'MathEditing';
}
init() {
const editor = this.editor;
editor.commands.add( 'math', new MathCommand( editor ) );
this._defineSchema();
this._defineConverters();
}
_defineSchema() {
const schema = this.editor.model.schema;
schema.register( 'mathtex', {
allowWhere: '$text',
isInline: true,
isObject: true,
allowAttributes: [ 'equation', 'type', 'display' ]
} );
}
_defineConverters() {
const conversion = this.editor.conversion;
// View -> Model
conversion.for( 'upcast' )
// MathJax inline way (e.g. <script type="math/tex">\sqrt{\frac{a}{b}}</script>)
.elementToElement( {
view: {
name: 'script',
attributes: {
type: 'math/tex'
}
},
model: ( viewElement, modelWriter ) => {
const equation = viewElement.getChild( 0 ).data.trim();
return modelWriter.createElement( 'mathtex', { equation, type: 'script', display: false } );
}
} )
// MathJax display way (e.g. <script type="math/tex; mode=display">\sqrt{\frac{a}{b}}</script>)
.elementToElement( {
view: {
name: 'script',
attributes: {
type: 'math/tex; mode=display'
}
},
model: ( viewElement, modelWriter ) => {
const equation = viewElement.getChild( 0 ).data.trim();
return modelWriter.createElement( 'mathtex', { equation, type: 'script', display: true } );
}
} )
// CKEditor 4 way (e.g. <span class="math-tex">\( \sqrt{\frac{a}{b}} \)</span>)
.elementToElement( {
view: {
name: 'span',
classes: [ 'math-tex' ]
},
model: ( viewElement, modelWriter ) => {
let equation = viewElement.getChild( 0 ).data.trim();
// Remove delimiters (e.g. \( \) or \[ \])
const hasInlineDelimiters = equation.includes( '\\(' ) && equation.includes( '\\)' );
const hasDisplayDelimiters = equation.includes( '\\[' ) && equation.includes( '\\]' );
if ( hasInlineDelimiters || hasDisplayDelimiters ) {
equation = equation.substring( 2, equation.length - 2 ).trim();
}
return modelWriter.createElement( 'mathtex', { equation, type: 'span', display: hasDisplayDelimiters } );
}
} );
// Model -> View (element)
conversion.for( 'editingDowncast' ).elementToElement( {
model: 'mathtex',
view: ( modelItem, viewWriter ) => {
const widgetElement = createMathtexEditingView( modelItem, viewWriter );
return toWidget( widgetElement, viewWriter );
}
} );
// Model -> Data
conversion.for( 'dataDowncast' ).elementToElement( {
model: 'mathtex',
view: createMathtexView
} );
// Create view for editor
function createMathtexEditingView( modelItem, viewWriter ) {
const equation = modelItem.getAttribute( 'equation' );
const display = modelItem.getAttribute( 'display' );
// CKEngine render multiple times if using span instead of div
const mathtexView = viewWriter.createContainerElement( 'div', {
style: display ? 'display: block;' : 'display: inline-block;',
class: 'mathtex'
} );
// Div is formatted as parent container
const uiElement = viewWriter.createUIElement( 'div', null, function( domDocument ) {
const domElement = this.toDomElement( domDocument );
renderEquation( equation, domElement, 'mathjax', display );
return domElement;
} );
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), uiElement );
return mathtexView;
}
// Create view for data
function createMathtexView( modelItem, viewWriter ) {
const equation = modelItem.getAttribute( 'equation' );
const type = modelItem.getAttribute( 'type' );
const display = modelItem.getAttribute( 'display' );
if ( type === 'span' ) {
const mathtexView = viewWriter.createContainerElement( 'span', {
class: 'math-tex'
} );
if ( display ) {
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), viewWriter.createText( '\\[' + equation + '\\]' ) );
} else {
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), viewWriter.createText( '\\(' + equation + '\\)' ) );
}
return mathtexView;
} else {
const mathtexView = viewWriter.createContainerElement( 'script', {
type: display ? 'math/tex; mode=display': 'math/tex'
} );
viewWriter.insert( viewWriter.createPositionAt( mathtexView, 0 ), viewWriter.createText( equation ) );
return mathtexView;
}
}
}
}

208
src/mathui.js Normal file
View File

@ -0,0 +1,208 @@
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ClickObserver from '@ckeditor/ckeditor5-engine/src/view/observer/clickobserver';
import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';
import clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
import MainFormView from './ui/mainformview';
// Need math commands from there
import MathEditing from './mathediting';
import pluginIcon from '../theme/icons/icon.svg';
const mathKeystroke = 'Ctrl+M';
export default class MathUI extends Plugin {
static get requires() {
return [ ContextualBalloon, MathEditing ];
}
static get pluginName() {
return 'MathUI';
}
init() {
const editor = this.editor;
editor.editing.view.addObserver( ClickObserver );
this._form = this._createFormView();
this._balloon = editor.plugins.get( ContextualBalloon );
this._createToolbarMathButton();
this._enableUserBalloonInteractions();
}
destroy() {
super.destroy();
this._form.destroy();
}
_showUI() {
const editor = this.editor;
const mathCommand = editor.commands.get( 'math' );
if ( !mathCommand.isEnabled ) {
return;
}
this._addFormView();
this._balloon.showStack( 'main' );
}
_createFormView() {
const editor = this.editor;
const mathCommand = editor.commands.get( 'math' );
const engine = 'mathjax';
const formView = new MainFormView( editor.locale, engine );
formView.mathInputView.bind( 'value' ).to( mathCommand, 'value' );
// Listen to 'submit' button click
this.listenTo( formView, 'submit', () => {
editor.execute( 'math', formView.equation );
this._closeFormView();
} );
// Listen to cancel button click
this.listenTo( formView, 'cancel', () => {
this._closeFormView();
} );
// Close plugin ui, if esc is pressed (while ui is focused)
formView.keystrokes.set( 'esc', ( data, cancel ) => {
this._closeFormView();
cancel();
} );
return formView;
}
_addFormView() {
if ( this._isFormInPanel ) {
return;
}
const editor = this.editor;
const mathCommand = editor.commands.get( 'math' );
this._balloon.add( {
view: this._form,
position: this._getBalloonPositionData(),
} );
if ( this._balloon.visibleView === this._form ) {
this._form.mathInputView.select();
}
this._form.equation = mathCommand.value || '';
}
_hideUI() {
if ( !this._isFormInPanel ) {
return;
}
const editor = this.editor;
this.stopListening( editor.ui, 'update' );
this.stopListening( this._balloon, 'change:visibleView' );
editor.editing.view.focus();
// Remove form first because it's on top of the stack.
this._removeFormView();
}
_closeFormView() {
const mathCommand = this.editor.commands.get( 'math' );
if ( mathCommand.value !== undefined ) {
this._removeFormView();
} else {
this._hideUI();
}
}
_removeFormView() {
if ( this._isFormInPanel ) {
this._form.saveButtonView.focus();
this._balloon.remove( this._form );
this.editor.editing.view.focus();
}
}
_getBalloonPositionData() {
const view = this.editor.editing.view;
const viewDocument = view.document;
const target = view.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() );
return { target };
}
_createToolbarMathButton() {
const editor = this.editor;
const mathCommand = editor.commands.get( 'math' );
const t = editor.t;
// Handle the `Ctrl+M` keystroke and show the panel.
editor.keystrokes.set( mathKeystroke, ( keyEvtData, cancel ) => {
// Prevent focusing the search bar in FF and opening new tab in Edge. #153, #154.
cancel();
if ( mathCommand.isEnabled ) {
this._showUI();
}
} );
this.editor.ui.componentFactory.add( 'math', locale => {
const button = new ButtonView( locale );
button.isEnabled = true;
button.label = t( 'Insert math' );
button.icon = pluginIcon;
button.keystroke = mathKeystroke;
button.tooltip = true;
button.isToggleable = true;
button.bind( 'isEnabled' ).to( mathCommand, 'isEnabled' );
this.listenTo( button, 'execute', () => this._showUI() );
return button;
} );
}
_enableUserBalloonInteractions() {
// Close the panel on the Esc key press when the editable has focus and the balloon is visible.
this.editor.keystrokes.set( 'Esc', ( data, cancel ) => {
if ( this._isUIVisible ) {
this._hideUI();
cancel();
}
} );
// Close on click outside of balloon panel element.
clickOutsideHandler( {
emitter: this._form,
activator: () => this._isFormInPanel,
contextElements: [ this._balloon.view.element ],
callback: () => this._hideUI()
} );
}
get _isUIVisible() {
const visibleView = this._balloon.visibleView;
return visibleView == this._form;
}
get _isFormInPanel() {
return this._balloon.hasView( this._form );
}
}

167
src/ui/mainformview.js Normal file
View File

@ -0,0 +1,167 @@
import View from '@ckeditor/ckeditor5-ui/src/view';
import ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
import LabeledInputView from '@ckeditor/ckeditor5-ui/src/labeledinput/labeledinputview';
import InputTextView from '@ckeditor/ckeditor5-ui/src/inputtext/inputtextview';
import LabelView from '@ckeditor/ckeditor5-ui/src/label/labelview';
import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';
import checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg';
import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';
import submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';
import MathView from './mathview';
import '../../theme/mathform.css';
export default class MainFormView extends View {
constructor( locale, engine ) {
super( locale );
const t = locale.t;
// Create key event & focus trackers
this._createKeyAndFocusTrackers();
// Equation input
this.mathInputView = this._createMathInput();
// Preview label
this.previewLabel = new LabelView( locale );
this.previewLabel.text = t( 'Equation preview' );
// Math element
this.mathView = new MathView( engine, locale );
// Submit button
this.saveButtonView = this._createButton( t( 'Save' ), checkIcon, 'ck-button-save', null );
this.saveButtonView.type = 'submit';
// Cancel button
this.cancelButtonView = this._createButton( t( 'Cancel' ), cancelIcon, 'ck-button-cancel', 'cancel' );
// Add UI elements to template
this.setTemplate( {
tag: 'form',
attributes: {
class: [
'ck',
'ck-math-form',
],
tabindex: '-1'
},
children: [
{
tag: 'div',
attributes: {
class: [
'ck-math-view'
]
},
children: [
this.mathInputView,
this.previewLabel,
this.mathView
]
},
this.saveButtonView,
this.cancelButtonView,
],
} );
}
render() {
super.render();
// Prevent default form submit event & trigger custom 'submit'
submitHandler( {
view: this,
} );
// Register form elements to focusable elements
const childViews = [
this.mathInputView,
this.saveButtonView,
this.cancelButtonView,
];
childViews.forEach( v => {
this._focusables.add( v );
this.focusTracker.add( v.element );
} );
// Listen to keypresses inside form element
this.keystrokes.listenTo( this.element );
}
focus() {
this._focusCycler.focusFirst();
}
get equation() {
return this.mathInputView.inputView.element.value;
}
set equation( equation ) {
this.mathInputView.inputView.element.value = equation;
this.mathView.value = equation;
}
_createKeyAndFocusTrackers() {
this.focusTracker = new FocusTracker();
this.keystrokes = new KeystrokeHandler();
this._focusables = new ViewCollection();
this._focusCycler = new FocusCycler( {
focusables: this._focusables,
focusTracker: this.focusTracker,
keystrokeHandler: this.keystrokes,
actions: {
focusPrevious: 'shift + tab',
focusNext: 'tab'
}
} );
}
_createMathInput() {
const t = this.locale.t;
// Create equation input
const mathInput = new LabeledInputView( this.locale, InputTextView );
const inputView = mathInput.inputView;
mathInput.infoText = t( 'Insert equation in TeX format.' );
inputView.on( 'input', () => {
this.mathView.value = inputView.element.value;
} );
return mathInput;
}
_createButton( label, icon, className, eventName ) {
const button = new ButtonView( this.locale );
button.set( {
label,
icon,
tooltip: true
} );
button.extendTemplate( {
attributes: {
class: className
}
} );
if ( eventName ) {
button.delegate( 'execute' ).to( this, eventName );
}
return button;
}
}

35
src/ui/mathview.js Normal file
View File

@ -0,0 +1,35 @@
import View from '@ckeditor/ckeditor5-ui/src/view';
import { renderEquation } from '../utils';
export default class MathView extends View {
constructor( engine, locale ) {
super( locale );
this.engine = engine;
this.set( 'value', '' );
this.on( 'change:value', () => {
this.updateMath();
} );
this.setTemplate( {
tag: 'div',
attributes: {
class: [
'ck',
'ck-math-preview'
],
}
} );
}
updateMath() {
renderEquation( this.value, this.element, this.engine );
}
render() {
super.render();
this.updateMath();
}
}

33
src/utils.js Normal file
View File

@ -0,0 +1,33 @@
export function renderEquation( equation, element, engine = 'katex', display = false ) {
if ( engine === 'mathjax' && typeof katex !== 'mathjax' ) {
if (display) {
element.innerHTML = '\\[' + equation + '\\]';
} else {
element.innerHTML = '\\(' + equation + '\\)';
}
/* eslint-disable */
MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, element ] );
/* eslint-enable */
}
else if ( engine === 'katex' && typeof katex !== 'undefined' ) {
/* eslint-disable */
katex.render( equation, element, {
throwOnError: false,
displayMode: display
} );
/* eslint-enable */
} else {
element.innerHTML = equation;
console.warn( 'math-tex-typesetting-missing: Missing the mathematical typesetting engine for tex.' );
}
}
export function getSelectedMathModelWidget( selection ) {
const selectedElement = selection.getSelectedElement();
if ( selectedElement && selectedElement.is( 'mathtex' ) ) {
return selectedElement;
}
return null;
}

1
theme/icons/icon.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.44 10.78" height="40.74" width="58.35"><path d="M8.15 0c-.06 0-.1.02-.11.03a.12.12 0 0 0-.02.01 6.81 6.81 0 0 0-2.32 4.9v.9a6.82 6.82 0 0 0 2.32 4.9.12.12 0 0 0 .02 0c.02.02.06.04.11.04.07 0 .12-.03.16-.07a.22.22 0 0 0 0-.32.12.12 0 0 0-.02-.02A4.4 4.4 0 0 1 7 8.44a7.62 7.62 0 0 1-.5-2.6v-.9c0-.82.19-1.76.5-2.6A4.4 4.4 0 0 1 8.3.42.12.12 0 0 0 8.3.39a.22.22 0 0 0 .08-.16.22.22 0 0 0-.07-.16.22.22 0 0 0-.16-.07zm4.83 0a.22.22 0 0 0-.16.07.22.22 0 0 0-.07.16c0 .08.05.13.08.16a.12.12 0 0 0 .01.02c.52.39.98 1.1 1.3 1.94.3.83.49 1.77.49 2.6v.88c0 .83-.18 1.78-.5 2.6a4.4 4.4 0 0 1-1.29 1.95.22.22 0 0 0-.01.33c.03.04.08.07.15.07.05 0 .09-.02.12-.03a.12.12 0 0 0 .02-.01 6.82 6.82 0 0 0 2.32-4.9v-.9a6.81 6.81 0 0 0-2.32-4.9.12.12 0 0 0-.02 0c-.03-.02-.06-.04-.12-.04zm-8.5.46c-.4 0-1.13.23-1.46 1.32-.06.2-.11.45-.33 1.58h-.64c-.1 0-.19-.01-.28.03a.25.25 0 0 0-.12.12.38.38 0 0 0-.03.17c0 .04 0 .1.04.14.03.04.07.07.11.08.09.03.16.02.26.02h.56l-.77 4.04c-.1.51-.19 1-.32 1.36-.06.18-.14.32-.22.4-.08.1-.16.13-.26.13-.03 0-.1 0-.2-.03.11-.05.2-.13.26-.2a.7.7 0 0 0 .13-.4.48.48 0 0 0-.16-.38.53.53 0 0 0-.35-.12c-.34 0-.7.3-.7.76 0 .27.14.5.34.64s.44.2.68.2c.33 0 .61-.17.83-.4.21-.21.37-.48.47-.69.18-.35.32-.84.43-1.25a14.17 14.17 0 0 0 .18-.8l.61-3.26h.81c.1 0 .2.01.3-.03.04-.03.09-.07.11-.13.02-.05.03-.1.03-.17 0-.05-.01-.1-.05-.14a.23.23 0 0 0-.11-.07c-.08-.03-.16-.02-.25-.02h-.73l.2-1.07a26.3 26.3 0 0 1 .24-1.07c.08-.17.22-.3.39-.3l.21.05a.7.7 0 0 0-.25.2.7.7 0 0 0-.13.4c0 .15.06.28.16.37.1.08.22.12.35.12.34 0 .7-.3.7-.76 0-.28-.15-.5-.35-.64-.2-.14-.45-.2-.7-.2zm5.4 2.78c-.6 0-1.06.37-1.36.76-.16.2-.27.4-.35.57-.07.18-.12.3-.12.42 0 .1.08.18.14.2.06.03.1.02.1.02.06 0 .12 0 .18-.04.05-.05.07-.1.08-.17v.02c.35-1.09 1-1.3 1.3-1.3.09 0 .2.01.29.09.09.07.17.2.17.5 0 .27-.18 1-.57 2.48a1.8 1.8 0 0 1-.37.75.7.7 0 0 1-.52.26c-.04 0-.13 0-.22-.03a.68.68 0 0 0 .3-.56.47.47 0 0 0-.18-.39.55.55 0 0 0-.32-.1c-.4 0-.7.33-.7.74 0 .28.16.5.38.63.21.13.48.18.73.18.39 0 .69-.2.89-.41.09-.1.15-.19.2-.27.2.36.59.68 1.16.68.6 0 1.05-.37 1.35-.76.15-.2.27-.4.34-.57.08-.18.12-.3.12-.42a.24.24 0 0 0-.11-.2c-.06-.03-.12-.02-.13-.02a.26.26 0 0 0-.18.06c-.05.05-.06.1-.07.14-.34 1.1-1.02 1.3-1.3 1.3-.17 0-.27-.06-.35-.17a.72.72 0 0 1-.11-.4c0-.22.06-.45.18-.91l.36-1.45c.03-.14.1-.44.25-.7.15-.25.36-.46.68-.46.03 0 .12 0 .22.03a.7.7 0 0 0-.32.56c0 .11.04.23.13.33.08.1.22.16.4.16.14 0 .3-.06.44-.18a.73.73 0 0 0 .24-.55c0-.32-.2-.54-.42-.66a1.52 1.52 0 0 0-.68-.16c-.34 0-.62.16-.82.34a1.8 1.8 0 0 0-.3.35 1.32 1.32 0 0 0-.5-.54 1.37 1.37 0 0 0-.63-.15z" style="line-height:1.25;-inkscape-font-specification:'Latin Modern Math'" font-weight="400" font-size="10.58" font-family="Latin Modern Math" letter-spacing="-1.06" word-spacing="0"/></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

35
theme/mathform.css Normal file
View File

@ -0,0 +1,35 @@
@import "@ckeditor/ckeditor5-ui/theme/mixins/_rwd.css";
.ck.ck-math-form {
display: flex;
align-items: flex-start;
flex-direction: row;
flex-wrap: nowrap;
@mixin ck-media-phone {
flex-wrap: wrap;
& .ck-math-view {
flex-basis: 100%;
& .ck-labeled-input {
flex-basis: 100%;
}
& .ck-label {
flex-basis: 100%;
}
}
& .ck-button {
flex-basis: 50%;
}
}
}
/* FIXME: mathjax isn't working with .ck.ck-reset_all * without this fix*/
.ck.ck-math-preview * {
vertical-align: initial;
text-align: center;
}