From c52e68f79ae44f962cca49f4f2fd83aceab1a7eb Mon Sep 17 00:00:00 2001 From: chris <kokosias@yahoo.gr> Date: Wed, 14 Oct 2020 13:40:33 +0300 Subject: [PATCH] math input rules --- wax-prosemirror-components/index.js | 1 - .../src/components/infoArea/InfoArea.js | 15 ------------ .../src/math/math-nodeview.js | 1 - .../src/math/math-plugin.js | 13 ++++++----- .../src/math/math-select.js | 17 +++++++------- wax-prosemirror-services/package.json | 1 + .../src/MathService/BlockInputRule.js | 23 +++++++++++++++++++ .../src/MathService/InlineInputRule.js | 23 +++++++++++++++++++ .../src/MathService/MathService.js | 12 ++++++++++ .../src/RulesService/Rules.js | 7 ++++++ 10 files changed, 82 insertions(+), 31 deletions(-) delete mode 100644 wax-prosemirror-components/src/components/infoArea/InfoArea.js create mode 100644 wax-prosemirror-services/src/MathService/BlockInputRule.js create mode 100644 wax-prosemirror-services/src/MathService/InlineInputRule.js diff --git a/wax-prosemirror-components/index.js b/wax-prosemirror-components/index.js index 0742df29f..0da2eedf1 100644 --- a/wax-prosemirror-components/index.js +++ b/wax-prosemirror-components/index.js @@ -1,4 +1,3 @@ -export { default as InfoArea } from './src/components/infoArea/InfoArea'; export { default as Overlay } from './src/components/Overlay'; export { default as Button } from './src/components/Button'; export { default as icons } from './src/icons/icons'; diff --git a/wax-prosemirror-components/src/components/infoArea/InfoArea.js b/wax-prosemirror-components/src/components/infoArea/InfoArea.js deleted file mode 100644 index ae6e088a0..000000000 --- a/wax-prosemirror-components/src/components/infoArea/InfoArea.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; -import styled from "styled-components"; - -const InfoAreaContainer = styled.div` - ${"" /* height: ${props => (props.height ? props.height : "30px")}; - position: fixed; - bottom: 0; - z-index: 9999; - background: #efefef; - width: 100%;*/}; -`; - -const InfoArea = () => <InfoAreaContainer />; - -export default InfoArea; diff --git a/wax-prosemirror-plugins/src/math/math-nodeview.js b/wax-prosemirror-plugins/src/math/math-nodeview.js index 81bcd0d33..1f9241d3a 100644 --- a/wax-prosemirror-plugins/src/math/math-nodeview.js +++ b/wax-prosemirror-plugins/src/math/math-nodeview.js @@ -1,5 +1,4 @@ /* eslint-disable */ - import { EditorState, TextSelection } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; import { StepMap } from 'prosemirror-transform'; diff --git a/wax-prosemirror-plugins/src/math/math-plugin.js b/wax-prosemirror-plugins/src/math/math-plugin.js index e9569035f..aebe23521 100644 --- a/wax-prosemirror-plugins/src/math/math-plugin.js +++ b/wax-prosemirror-plugins/src/math/math-plugin.js @@ -1,3 +1,4 @@ +/* eslint-disable */ import { Plugin as ProsePlugin, PluginKey } from 'prosemirror-state'; import { MathView } from './math-nodeview'; /** @@ -11,13 +12,13 @@ function createMathView(displayMode) { * Docs says that for any function proprs, the current plugin instance * will be bound to `this`. However, the typings don't reflect this. */ - const pluginState = mathPluginKey.getState(view.state); + let pluginState = mathPluginKey.getState(view.state); if (!pluginState) { throw new Error('no math plugin!'); } - const nodeViews = pluginState.activeNodeViews; + let nodeViews = pluginState.activeNodeViews; // set up NodeView - const nodeView = new MathView( + let nodeView = new MathView( node, view, getPos, @@ -30,8 +31,8 @@ function createMathView(displayMode) { return nodeView; }; } -const mathPluginKey = new PluginKey('prosemirror-math'); -const mathPluginSpec = { +let mathPluginKey = new PluginKey('prosemirror-math'); +let mathPluginSpec = { key: mathPluginKey, state: { init(config, instance) { @@ -46,7 +47,7 @@ const mathPluginSpec = { * information about any new MathViews that were created by this transaction. * As a result, the cursor position may be wrong for any newly created math blocks. */ - const pluginState = mathPluginKey.getState(oldState); + let pluginState = mathPluginKey.getState(oldState); if (pluginState) { for (let mathView of pluginState.activeNodeViews) { mathView.updateCursorPos(newState); diff --git a/wax-prosemirror-plugins/src/math/math-select.js b/wax-prosemirror-plugins/src/math/math-select.js index 9d9e87454..25989cb3d 100644 --- a/wax-prosemirror-plugins/src/math/math-select.js +++ b/wax-prosemirror-plugins/src/math/math-select.js @@ -1,20 +1,21 @@ +/* eslint-disable */ + // prosemirror imports import { Plugin as ProsePlugin } from 'prosemirror-state'; import { DecorationSet, Decoration } from 'prosemirror-view'; - +//////////////////////////////////////////////////////////// /** * Uses the selection to determine which math_select decorations * should be applied to the given document. * @param arg Should be either a Transaction or an EditorState, * although any object with `selection` and `doc` will work. */ - -const checkSelection = arg => { - const { from, to } = arg; - const { content } = arg.selection.content(); - const result = []; +let checkSelection = arg => { + let { from, to } = arg.selection; + let content = arg.selection.content().content; + let result = []; content.descendants((node, pos, parent) => { - if (node.type.name === 'text') { + if (node.type.name == 'text') { return false; } if (node.type.name.startsWith('math_')) { @@ -52,7 +53,7 @@ const mathSelectPlugin = new ProsePlugin({ if (!tr.selection || !tr.selectionSet) { return oldState; } - const sel = checkSelection(tr); + let sel = checkSelection(tr); return sel; }, }, diff --git a/wax-prosemirror-services/package.json b/wax-prosemirror-services/package.json index 13876b3a1..60282baf2 100644 --- a/wax-prosemirror-services/package.json +++ b/wax-prosemirror-services/package.json @@ -23,6 +23,7 @@ "prosemirror-schema-list": "1.1.4", "prosemirror-state": "1.3.3", "prosemirror-transform": "1.2.6", + "prosemirror-inputrules": "1.1.2", "prosemirror-view": "1.15.2", "styled-components": "^4.2.0", "uuid": "^7.0.3", diff --git a/wax-prosemirror-services/src/MathService/BlockInputRule.js b/wax-prosemirror-services/src/MathService/BlockInputRule.js new file mode 100644 index 000000000..1b13412fb --- /dev/null +++ b/wax-prosemirror-services/src/MathService/BlockInputRule.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +import { InputRule } from 'prosemirror-inputrules'; +import { NodeSelection } from 'prosemirror-state'; + +const blockInputRule = (pattern, nodeType, getAttrs) => { + return new InputRule(pattern, (state, match, start, end) => { + let $start = state.doc.resolve(start); + let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs; + if ( + !$start + .node(-1) + .canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType) + ) + return null; + let tr = state.tr + .delete(start, end) + .setBlockType(start, start, nodeType, attrs); + return tr.setSelection( + NodeSelection.create(tr.doc, tr.mapping.map($start.pos - 1)), + ); + }); +}; +export default blockInputRule; diff --git a/wax-prosemirror-services/src/MathService/InlineInputRule.js b/wax-prosemirror-services/src/MathService/InlineInputRule.js new file mode 100644 index 000000000..d0ce6c570 --- /dev/null +++ b/wax-prosemirror-services/src/MathService/InlineInputRule.js @@ -0,0 +1,23 @@ +import { InputRule } from 'prosemirror-inputrules'; + +const inlineInputRule = (pattern, nodeType, getAttrs) => { + return new InputRule(pattern, (state, match, start, end) => { + const $start = state.doc.resolve(start); + const index = $start.index(); + const $end = state.doc.resolve(end); + // get attrs + const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs; + // check if replacement valid + if (!$start.parent.canReplaceWith(index, $end.index(), nodeType)) { + return null; + } + // perform replacement + return state.tr.replaceRangeWith( + start, + end, + nodeType.create(attrs, nodeType.schema.text(match[1])), + ); + }); +}; + +export default inlineInputRule; diff --git a/wax-prosemirror-services/src/MathService/MathService.js b/wax-prosemirror-services/src/MathService/MathService.js index 1cc778bae..8584f7279 100644 --- a/wax-prosemirror-services/src/MathService/MathService.js +++ b/wax-prosemirror-services/src/MathService/MathService.js @@ -5,6 +5,8 @@ import { } from 'wax-prosemirror-schema'; import { mathPlugin, mathSelectPlugin } from 'wax-prosemirror-plugins'; import Service from '../Service'; +import inlineInputRule from './InlineInputRule'; +import blockInputRule from './BlockInputRule'; class MathService extends Service { name = 'MathService'; @@ -12,6 +14,16 @@ class MathService extends Service { boot() { this.app.PmPlugins.add('mathplugin', mathPlugin); this.app.PmPlugins.add('mathselectplugin', mathSelectPlugin); + const schema = this.container.get('Schema'); + const rules = this.container.get('Rules'); + const newRules = [ + inlineInputRule( + /(?<!\\)\$(.+)(?<!\\)\$/, + schema.schema.nodes.math_inline, + ), + blockInputRule(/^\$\$\s+$/, schema.schema.nodes.math_display), + ]; + // rules.addRule(newRules); } register() { diff --git a/wax-prosemirror-services/src/RulesService/Rules.js b/wax-prosemirror-services/src/RulesService/Rules.js index bb8767832..107bbd025 100644 --- a/wax-prosemirror-services/src/RulesService/Rules.js +++ b/wax-prosemirror-services/src/RulesService/Rules.js @@ -6,6 +6,10 @@ import { smartQuotes, } from 'prosemirror-inputrules'; +// TODO add through service. +import inlineInputRule from '../MathService/InlineInputRule'; +import blockInputRule from '../MathService/BlockInputRule'; + @injectable() class Rules { constructor(plugins, schema) { @@ -17,6 +21,7 @@ class Rules { addRule(rules) { this.extendedRules.push(...rules); + // this.extendedRules = this.allRules().concat(...rules); } createRules() { @@ -50,6 +55,8 @@ class Rules { this.schema.nodes.heading, match => ({ level: match[1].length }), ), + inlineInputRule(/(?<!\\)\$(.+)(?<!\\)\$/, this.schema.nodes.math_inline), + blockInputRule(/^\$\$\s+$/, this.schema.nodes.math_display), ]; } } -- GitLab