diff --git a/editors/editoria/config-overrides.js b/editors/editoria/config-overrides.js index 82c74c17dd0161dd58670ef1a2c591870a92e789..e2cf94482e8e7bc53cdb65bef9c758bbf04a1a3e 100644 --- a/editors/editoria/config-overrides.js +++ b/editors/editoria/config-overrides.js @@ -12,7 +12,11 @@ module.exports = function override(config, env) { [require("@babel/preset-env"), { modules: false }], require("@babel/preset-react") ], - plugins: [require("@babel/plugin-proposal-class-properties")] + plugins: [ + ["@babel/plugin-proposal-decorators", { legacy: true }], + "babel-plugin-parameter-decorator", + ["@babel/plugin-proposal-class-properties", { loose: true }] + ] } }, { diff --git a/editors/editoria/jsconfig.json b/editors/editoria/jsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..504cd646e14906b4db8e943f9bfb10ab80162cee --- /dev/null +++ b/editors/editoria/jsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "experimentalDecorators": true + } +} diff --git a/editors/editoria/package.json b/editors/editoria/package.json index 84d3efed8895446b76752176c05f02aa90af2be8..82026527628085fe74ffc4af7b2029c0904a35b2 100644 --- a/editors/editoria/package.json +++ b/editors/editoria/package.json @@ -13,7 +13,8 @@ "wax-prosemirror-core": "^0.0.3", "wax-prosemirror-layouts": "^0.0.3", "wax-prosemirror-schema": "^0.0.3", - "wax-prosemirror-themes": "^0.0.3" + "wax-prosemirror-themes": "^0.0.3", + "babel-plugin-parameter-decorator": "1.0.12" }, "scripts": { "start": "react-app-rewired start", diff --git a/editors/editoria/src/EditorConfig.js b/editors/editoria/src/EditorConfig.js index e0d225b7145d919dab7f8b7108b9031230ad67f2..4dbf29f8b2c5dc575ab40f9daa50943fee6648e0 100644 --- a/editors/editoria/src/EditorConfig.js +++ b/editors/editoria/src/EditorConfig.js @@ -31,7 +31,9 @@ import { LinkToolTipPlugin, FindAndReplacePlugin, TrackChangePlugin, - MenuBarPlugin + MenuBarPlugin, + LinkService, + LayoutService } from "wax-prosemirror-plugins"; import { MainMenuBar, SideMenuBar } from "wax-prosemirror-components"; @@ -98,7 +100,9 @@ const plugins = [ }) ]; +const services = [new LayoutService(), new LinkService()]; + // Add Rules const rules = [emDash, ellipsis]; -export { schema, keys, plugins, rules }; +export { schema, keys, plugins, rules, services }; diff --git a/editors/editoria/src/Editoria.js b/editors/editoria/src/Editoria.js index 594b9b630e9c723c3ab7f2c62a448aecd0cccde2..dd3b7e463c6dbb8524ecd9518156c9acfb11ad58 100644 --- a/editors/editoria/src/Editoria.js +++ b/editors/editoria/src/Editoria.js @@ -3,7 +3,7 @@ import styled, { createGlobalStyle } from "styled-components"; import { setLayout } from "wax-prosemirror-core"; -import { schema, keys, plugins, rules } from "./EditorConfig"; +import { schema, keys, plugins, rules, services } from "./EditorConfig"; import text from "./text"; @@ -11,7 +11,8 @@ const options = { schema, plugins, keys, - rules + rules, + services }; const GlobalStyle = createGlobalStyle` diff --git a/package.json b/package.json index f58069cdae2c41a537cd5c44185c321617693ee6..090c5c4d74b83d9045ebf26d7ac9ce1175d263dd 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "version": "0.0.1", "main": "index.js", "author": "Collaborative Knowledge Foundation", - "description": - "Monorepo for wax-prosemirror, its components and its integrations", + "description": "Monorepo for wax-prosemirror, its components and its integrations", "repository": { "type": "git", "url": "git@gitlab.coko.foundation:wax/wax-prosemirror.git" @@ -13,8 +12,7 @@ "private": true, "scripts": { "bootstrap": "lerna bootstrap --no-ci --hoist", - "clean": - "yarn run clean:artifacts && yarn run clean:packages && yarn run clean:root", + "clean": "yarn run clean:artifacts && yarn run clean:packages && yarn run clean:root", "clean:artifacts": "lerna run clean --parallel", "clean:packages": "lerna clean --yes", "clean:root": "rm -rf node_modules", @@ -26,6 +24,7 @@ "dependencies": {}, "devDependencies": { "@babel/plugin-proposal-class-properties": "^7.0.0", + "@babel/plugin-proposal-decorators": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "css-loader": "^0.28.11", diff --git a/wax-prosemirror-components/index.js b/wax-prosemirror-components/index.js index 57975b195f0dac1e3cb6df2f28ee60a1b99105b8..64873c03315b9973ecba16cb461c6a789b5e57bf 100644 --- a/wax-prosemirror-components/index.js +++ b/wax-prosemirror-components/index.js @@ -1,5 +1,5 @@ export { default as MainMenuBar } from "./src/mainMenuBar/MainMenuBar"; export { default as SideMenuBar } from "./src/sideMenuBar/SideMenuBar"; export { default as InfoArea } from "./src/components/infoArea/InfoArea"; -export { default as componentPlugin } from "./src/components/componentPlugin"; +export { default as componentPlugin } from "wax-prosemirror-core/src/componentPlugin"; export { default as Overlay } from "./src/components/Overlay"; diff --git a/wax-prosemirror-components/src/components/componentPlugin.js b/wax-prosemirror-components/src/components/componentPlugin.js deleted file mode 100644 index c9d2ba14bd07451fadae37079d8fccb3bbaaadab..0000000000000000000000000000000000000000 --- a/wax-prosemirror-components/src/components/componentPlugin.js +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; -import WaxContext from "wax-prosemirror-core/src/helpers/WaxContext"; - -const ComponentPlugin = renderArea => props => ( - <WaxContext.Consumer> - {context => { - const { state = { plugins: [] } } = context.view; - const pluginComponent = state.plugins.map(plugin => { - if ( - state[plugin.key] && - state[plugin.key].renderArea === renderArea && - state[plugin.key].component - ) { - const Component = state[plugin.key].component; - return ( - <Component key={plugin.key} view={context.view} state={state} /> - ); - } - - return null; - }); - - return pluginComponent; - }} - </WaxContext.Consumer> -); - -export default ComponentPlugin; diff --git a/wax-prosemirror-core/index.js b/wax-prosemirror-core/index.js index a9e4bb31a3aa3226b33695a0c10c481d355ed442..47330de9818decd968cf099d2c638707ee28a7b4 100644 --- a/wax-prosemirror-core/index.js +++ b/wax-prosemirror-core/index.js @@ -3,3 +3,4 @@ export { default as CreateSchema } from "./src/config/classes/CreateSchema"; export { default as setLayout } from "./src/helpers/setLayout"; export { default as CreateShortCuts } from "./src/config/classes/CreateShortCuts"; export { default as WaxContext } from "./src/helpers/WaxContext"; +export { default as Container } from "./src/ioc"; diff --git a/wax-prosemirror-core/package.json b/wax-prosemirror-core/package.json index ceb04f8d09e16a790bceb7ad603191a6e34ccbc6..45b97b43b05a03383ac1fd3b4062ce86743687c6 100644 --- a/wax-prosemirror-core/package.json +++ b/wax-prosemirror-core/package.json @@ -23,7 +23,10 @@ "prosemirror-view": "^1.13.4", "react": "^16.8.6", "react-dom": "^16.8.6", - "styled-components": "^4.2.0" + "styled-components": "^4.2.0", + "inversify": "^5.0.1", + "inversify-inject-decorators": "^3.1.0", + "reflect-metadata": "^0.1.13" }, "devDependencies": { "mocha": "^3.4.2", diff --git a/wax-prosemirror-core/src/Wax.js b/wax-prosemirror-core/src/Wax.js index e1657c505a885956b50b1cc8701de8719c5a2912..9da883db8ce59123ff802705bbe66424f4ae0dac 100644 --- a/wax-prosemirror-core/src/Wax.js +++ b/wax-prosemirror-core/src/Wax.js @@ -1,11 +1,13 @@ import React, { Component } from "react"; +import WaxProvider from "./ioc-react"; +import container from "./ioc"; + import debounce from "lodash/debounce"; import styled from "styled-components"; import { DOMParser, DOMSerializer } from "prosemirror-model"; import { DefaultLayout } from "wax-prosemirror-layouts"; -import WaxContext from "./helpers/WaxContext"; import WaxView from "./WaxView"; import defaultPlugins from "./config/defaultPlugins"; import placeholder from "./config/plugins/placeholder"; @@ -42,7 +44,7 @@ const LayoutWrapper = styled.div` class Wax extends Component { componentWillMount() { const { value, onChange, options } = this.props; - const { schema, plugins, keys, rules } = options; + const { schema, plugins, keys, rules, services } = options; const WaxOnchange = onChange ? onChange : value => true; const WaxShortCuts = keys @@ -61,6 +63,12 @@ class Wax extends Component { WaxRules ]); + services.map(plugin => { + if (plugin.register) { + plugin.register(); + } + }); + this.WaxOptions = { schema, plugins: finalPlugins @@ -70,6 +78,12 @@ class Wax extends Component { const serialize = serializer(schema); this.WaxOptions.doc = parse(editorContent); + services.map(plugin => { + if (plugin.register) { + plugin.boot(); + } + }); + this.onChange = debounce( value => { WaxOnchange(serialize(value)); @@ -115,9 +129,9 @@ class Wax extends Component { user={user} > {({ view, editor }) => ( - <WaxContext.Provider value={{ view }}> + <WaxProvider view={view} container={container}> <WaxRender editor={editor} /> - </WaxContext.Provider> + </WaxProvider> )} </WaxView> </LayoutWrapper> diff --git a/wax-prosemirror-core/src/componentPlugin.js b/wax-prosemirror-core/src/componentPlugin.js new file mode 100644 index 0000000000000000000000000000000000000000..8a44c7a93ca7227e90cfc931f2e674145d677d99 --- /dev/null +++ b/wax-prosemirror-core/src/componentPlugin.js @@ -0,0 +1,16 @@ +import React from "react"; +import { useInjection } from "./ioc-react"; + +const ComponentPlugin = renderArea => props => { + const Layout = useInjection("Layout"); + console.log(Layout); + const { Component } = Layout.render(renderArea); + + return Component ? <Component renderArea={renderArea} /> : null; + return Component.map(Component => + Component.renderArea === renderArea ? ( + <Component.component renderArea={renderArea} /> + ) : null + ); +}; +export default ComponentPlugin; diff --git a/wax-prosemirror-core/src/ioc-react.js b/wax-prosemirror-core/src/ioc-react.js new file mode 100644 index 0000000000000000000000000000000000000000..8f82eec3d21521d1a3df9622c580350edc1fe9ec --- /dev/null +++ b/wax-prosemirror-core/src/ioc-react.js @@ -0,0 +1,24 @@ +import React, { useContext } from "react"; + +const WaxContext = React.createContext({ view: null, container: null }); + +export default props => { + console.log(props); + return ( + <WaxContext.Provider + value={{ container: props.container, view: props.view }} + > + {props.children} + </WaxContext.Provider> + ); +}; + +export function useInjection(identifier) { + const { container } = useContext(WaxContext); + + if (!container) { + throw new Error(); + } + + return container.isBound(identifier) ? container.get(identifier) : null; +} diff --git a/wax-prosemirror-core/src/ioc.js b/wax-prosemirror-core/src/ioc.js new file mode 100644 index 0000000000000000000000000000000000000000..5e07d5aee6d12d5d1dfabde867e3f707f3f4ca0b --- /dev/null +++ b/wax-prosemirror-core/src/ioc.js @@ -0,0 +1,6 @@ +import { Container } from "inversify"; +import "reflect-metadata"; + +const container = new Container(); + +export default container; diff --git a/wax-prosemirror-plugins/index.js b/wax-prosemirror-plugins/index.js index 47d507af1b057b7e05040236a397dae419eaa45f..07e822af8ca4fd1bfcf0a5b086269711789a6847 100644 --- a/wax-prosemirror-plugins/index.js +++ b/wax-prosemirror-plugins/index.js @@ -2,3 +2,5 @@ export { default as TrackChangePlugin } from "./src/trackChanges/TrackChangePlug export { default as FindAndReplacePlugin } from "./src/FindAndReplacePlugin"; export { default as MenuBarPlugin } from "./src/menuBar/MenuBarPlugin"; export { default as OverlayPlugin } from "./src/overlay/OverlayPlugin"; +export { default as LayoutService } from "./src/LayoutService/LayoutService"; +export { default as LinkService } from "./src/LinkService/LinkService"; diff --git a/wax-prosemirror-plugins/package.json b/wax-prosemirror-plugins/package.json index eedc5ee50e80506389d1cfa7d5c9c4616c5080dd..76421fc642c5f7141e9a9ffc25472cdfa8821e21 100644 --- a/wax-prosemirror-plugins/package.json +++ b/wax-prosemirror-plugins/package.json @@ -10,6 +10,9 @@ }, "dependencies": { "prosemirror-state": "^1.2.2", - "prosemirror-view": "^1.13.1" + "prosemirror-view": "^1.13.1", + "inversify": "^5.0.1", + "inversify-inject-decorators": "^3.1.0", + "reflect-metadata": "^0.1.13" } } diff --git a/wax-prosemirror-plugins/src/LayoutService/Layout.js b/wax-prosemirror-plugins/src/LayoutService/Layout.js new file mode 100644 index 0000000000000000000000000000000000000000..f88b2244e16ab0758be1b92f3e858420b8ed8b3b --- /dev/null +++ b/wax-prosemirror-plugins/src/LayoutService/Layout.js @@ -0,0 +1,17 @@ +import { injectable, multiInject } from "inversify"; + +@injectable() +export default class Layout { + constructor() { + this.components = new Map(); + } + + addComponent(renderArea, component) { + this.components.set(renderArea, component); + return this; + } + + render(renderArea) { + return { Component: this.components.get(renderArea) }; + } +} diff --git a/wax-prosemirror-plugins/src/LayoutService/LayoutService.js b/wax-prosemirror-plugins/src/LayoutService/LayoutService.js new file mode 100644 index 0000000000000000000000000000000000000000..b98b5fb9e763c0ce8336c3d0ac58d9dff967e44d --- /dev/null +++ b/wax-prosemirror-plugins/src/LayoutService/LayoutService.js @@ -0,0 +1,11 @@ +import Service from "../Service"; +import Layout from "./Layout"; +export default class LayoutService extends Service { + name = "LayoutService"; + register() { + this.container + .bind("Layout") + .to(Layout) + .inSingletonScope(); + } +} diff --git a/wax-prosemirror-plugins/src/LinkService/LinkPlugin.js b/wax-prosemirror-plugins/src/LinkService/LinkPlugin.js new file mode 100644 index 0000000000000000000000000000000000000000..206e598df6cb29a5c439756c07dc4bb55246d5ef --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/LinkPlugin.js @@ -0,0 +1,40 @@ +import React from "react"; +import { injectable, multiInject, inject, named } from "inversify"; + +const Component1 = props => <div>{props.renderArea}</div>; +const Component2 = props => <div>{props.renderArea}</div>; + +@injectable() +export default class LinkPlugin { + items = [ + { + link: "1", + link2: "3" + }, + { + link: "2", + link2: "4" + } + ]; + plugins = []; + + constructor( + @inject("Layout") layout, + @inject("findPlugin") find, + @inject("placeholderPlugin") placeholder + ) { + this.find = find; + this.placeholder = placeholder; + + //console.log(this.find, this.placeholder); + layout + .addComponent("topBar", Component2) + .addComponent("leftSideBar", Component1); + + this.initPlugins(); + } + + initPlugins() { + this.plugins = [this.placeholder(this.items[1]), this.find("s")]; + } +} diff --git a/wax-prosemirror-plugins/src/LinkService/LinkService.js b/wax-prosemirror-plugins/src/LinkService/LinkService.js new file mode 100644 index 0000000000000000000000000000000000000000..6d2900ab0c8dd23401762c9459126448628557a8 --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/LinkService.js @@ -0,0 +1,21 @@ +import LinkPlugin from "./LinkPlugin"; +import Service from "../Service"; +import find from "./pmPlugins/find"; +import placeholder from "./pmPlugins/placeholder"; + +export default class myLinkPluginService extends Service { + name = "LinkPlugin"; + + boot() { + const test = this.container.get("LinkPlugin"); + console.log(test); + } + + register() { + this.container.bind(this.name).to(LinkPlugin); + + this.container.bind("findPlugin").toFactory(find); + + this.container.bind("placeholderPlugin").toFactory(placeholder); + } +} diff --git a/wax-prosemirror-plugins/src/LinkService/pmPlugins/find.js b/wax-prosemirror-plugins/src/LinkService/pmPlugins/find.js new file mode 100644 index 0000000000000000000000000000000000000000..4a6d8bbb585b54773bbfc1d3c04420d674ea70b2 --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/pmPlugins/find.js @@ -0,0 +1,14 @@ +import { Plugin, PluginKey } from "prosemirror-state"; +export const findLink = new PluginKey("findLink"); + +export default items => { + return () => + new Plugin({ + key: findLink, + state: { + init() { + return items; + } + } + }); +}; diff --git a/wax-prosemirror-plugins/src/LinkService/pmPlugins/placeholder.js b/wax-prosemirror-plugins/src/LinkService/pmPlugins/placeholder.js new file mode 100644 index 0000000000000000000000000000000000000000..6ca4468e400e53805fef5356e43d531ef96135f7 --- /dev/null +++ b/wax-prosemirror-plugins/src/LinkService/pmPlugins/placeholder.js @@ -0,0 +1,14 @@ +import { Plugin, PluginKey } from "prosemirror-state"; +export const placeholderLink = new PluginKey("placeholderLink"); + +export default items => { + return () => + new Plugin({ + key: placeholderLink, + state: { + init() { + return items; + } + } + }); +}; diff --git a/wax-prosemirror-plugins/src/Service.js b/wax-prosemirror-plugins/src/Service.js new file mode 100644 index 0000000000000000000000000000000000000000..d3c2e4603c7bf00ba4f4467757ea41b0091c95a4 --- /dev/null +++ b/wax-prosemirror-plugins/src/Service.js @@ -0,0 +1,9 @@ +import { Container } from "wax-prosemirror-core"; + +export default class Service { + constructor() { + this.container = Container; + } + + boot() {} +} diff --git a/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js b/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js index deda627775b21ec019c016a3df2160fbd61ff392..f923f2906c629b4d146aa4c87553071f02589c43 100644 --- a/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js +++ b/wax-prosemirror-plugins/src/overlay/OverlayPlugin.js @@ -27,63 +27,54 @@ const OverlayPlugin = args => { export default OverlayPlugin; - -reactComponent - -overlayPlugin position - -linkPlugin showhide - - -linkPlugin = createplugin (reactComponent, overlay) - - - -const createPlugin = (reactComponent, overlayPlugin) => { - - return new Plugin ({ - key, - state, - view, - }) -} - -createPlugin = () => class { - name: "test", - renderArea, - component: () => {}, - itemsMenus: [], - plugins: [plugin, plugin] -} - - - -class createPlugin { - constructor() { - this.name - this.plugins.push(overlayPlugin(Component, showCommand)) - } - plugins () { return []} -} - - -class waxPlugin { - constructor() { - this.name - - } - - createPlugin () { - - } -} - -class linkPlugin extends waxPlugin { - component: - renderArea: - showCommand: - itemsMenus: - -} - -new(OverlayPlugin) \ No newline at end of file +// reactComponent + +// overlayPlugin position + +// linkPlugin showhide + +// linkPlugin = createplugin(reactComponent, overlay); + +// const createPlugin = (reactComponent, overlayPlugin) => { +// return new Plugin({ +// key, +// state, +// view +// }); +// }; + +// createPlugin = () => class { +// name: "test", +// renderArea, +// component: () => {}, +// itemsMenus: [], +// plugins: [plugin, plugin] +// } + +// class createPlugin { +// constructor() { +// this.name; +// this.plugins.push(overlayPlugin(Component, showCommand)); +// } +// plugins() { +// return []; +// } +// } + +// class waxPlugin { +// constructor() { +// this.name; +// } + +// createPlugin() {} +// } + +// class linkPlugin extends waxPlugin { +// component: +// renderArea: +// showCommand: +// itemsMenus: + +// } + +// new(OverlayPlugin)