Skip to content
Snippets Groups Projects
Commit 1ded5904 authored by Giannis Kopanas's avatar Giannis Kopanas
Browse files

feat(schema): add Schema services

parent b9f85103
No related branches found
No related tags found
1 merge request!45Develop
Showing
with 417 additions and 30 deletions
...@@ -3,7 +3,7 @@ import styled, { createGlobalStyle } from "styled-components"; ...@@ -3,7 +3,7 @@ import styled, { createGlobalStyle } from "styled-components";
import { EditoriaLayout } from "wax-prosemirror-layouts"; import { EditoriaLayout } from "wax-prosemirror-layouts";
import { Wax } from "wax-prosemirror-core"; import { Wax } from "wax-prosemirror-core";
import { schema, keys, plugins, rules, services } from "./EditorConfig"; import { schema, keys, plugins, services } from "./EditorConfig";
import { config } from "./config"; import { config } from "./config";
import text from "./text"; import text from "./text";
...@@ -12,7 +12,6 @@ const options = { ...@@ -12,7 +12,6 @@ const options = {
schema, schema,
plugins, plugins,
keys, keys,
rules,
services services
}; };
......
import { Container } from "inversify"; import { Container } from "inversify";
import { Schema } from "prosemirror-model";
import "reflect-metadata"; import "reflect-metadata";
import Config from "./Config/Config"; import Config from "./Config/Config";
import defaultConfig from "./Config/defaultConfig"; import defaultConfig from "./Config/defaultConfig";
...@@ -47,6 +48,11 @@ export default class Application { ...@@ -47,6 +48,11 @@ export default class Application {
return this.PmPlugins.getAll(); return this.PmPlugins.getAll();
} }
getSchema() {
const schema = this.container.get("Schema");
return new Schema(schema.getSchema());
}
static create(config) { static create(config) {
/* /*
Create Container Create Container
......
...@@ -6,11 +6,13 @@ import { ...@@ -6,11 +6,13 @@ import {
TextStyleService, TextStyleService,
PlaceholderService, PlaceholderService,
ImageService, ImageService,
RulesService RulesService,
SchemaService
} from "wax-prosemirror-plugins"; } from "wax-prosemirror-plugins";
export default { export default {
services: [ services: [
new SchemaService(),
new LayoutService(), new LayoutService(),
new MenuService(), new MenuService(),
new RedoUndoService(), new RedoUndoService(),
......
...@@ -49,7 +49,7 @@ class Wax extends Component { ...@@ -49,7 +49,7 @@ class Wax extends Component {
componentWillMount() { componentWillMount() {
const { value, onChange, options } = this.props; const { value, onChange, options } = this.props;
const { schema, plugins, keys, rules } = options; const { plugins, keys, rules } = options;
const WaxOnchange = onChange ? onChange : value => true; const WaxOnchange = onChange ? onChange : value => true;
// const WaxShortCuts = keys // const WaxShortCuts = keys
...@@ -64,6 +64,8 @@ class Wax extends Component { ...@@ -64,6 +64,8 @@ class Wax extends Component {
...this.application.getPlugins() ...this.application.getPlugins()
]); ]);
const schema = this.application.getSchema();
this.WaxOptions = { this.WaxOptions = {
schema, schema,
plugins: finalPlugins plugins: finalPlugins
......
export { export { default as TrackChangePlugin } from "./src/trackChanges/TrackChangePlugin";
default as TrackChangePlugin
} from "./src/trackChanges/TrackChangePlugin";
export { default as FindAndReplacePlugin } from "./src/FindAndReplacePlugin"; export { default as FindAndReplacePlugin } from "./src/FindAndReplacePlugin";
export { default as OverlayPlugin } from "./src/overlay/OverlayPlugin"; export { default as OverlayPlugin } from "./src/overlay/OverlayPlugin";
export { default as LinkService } from "./src/LinkService/LinkService"; export { default as LinkService } from "./src/LinkService/LinkService";
export { default as MenuService } from "./src/MenuService/MenuService"; export { default as MenuService } from "./src/MenuService/MenuService";
export { export { default as RedoUndoService } from "./src/RedoUndoService/RedoUndoService";
default as RedoUndoService export { default as AnnotationService } from "./src/AnnotationService/AnnotationService";
} from "./src/RedoUndoService/RedoUndoService"; export { default as TextStyleService } from "./src/TextStyleService/TextStyleService";
export { export { default as PlaceholderService } from "./src/PlaceholderService/PlaceholderService";
default as AnnotationService
} from "./src/AnnotationService/AnnotationService";
export {
default as TextStyleService
} from "./src/TextStyleService/TextStyleService";
export {
default as PlaceholderService
} from "./src/PlaceholderService/PlaceholderService";
export { default as ImageService } from "./src/ImageService/ImageService"; export { default as ImageService } from "./src/ImageService/ImageService";
export { default as RulesService } from "./src/RulesService/RulesService"; export { default as RulesService } from "./src/RulesService/RulesService";
export { default as SchemaService } from "./src/SchemaService/SchemaService";
export { default as Tool } from "./src/lib/Tools"; export { default as Tool } from "./src/lib/Tools";
...@@ -27,11 +27,3 @@ export default class Menu { ...@@ -27,11 +27,3 @@ export default class Menu {
return view => <MenuWrapper items={this.toolGroups} view={view} />; return view => <MenuWrapper items={this.toolGroups} view={view} />;
} }
} }
// {
// templateArea: "topBar",
// tools: [
// "redo-undo",
// { name: "Annotations", exclude: [], include: [] }
// ]
// }
...@@ -2,10 +2,96 @@ import Service from "wax-prosemirror-core/src/services/Service"; ...@@ -2,10 +2,96 @@ import Service from "wax-prosemirror-core/src/services/Service";
import placeholderPlugin from "./pmPlugins/placeholderPlugin"; import placeholderPlugin from "./pmPlugins/placeholderPlugin";
const PLUGIN_KEY = "imagePlaceHolder"; const PLUGIN_KEY = "imagePlaceHolder";
const blockLevelToDOM = node => {
const attrs = node.attrs.track.length
? {
class: node.attrs.class,
"data-track": JSON.stringify(node.attrs.track)
}
: { class: node.attrs.class };
return attrs;
};
const parseTracks = str => {
if (!str) {
return [];
}
let tracks;
try {
tracks = JSON.parse(str);
} catch (error) {
return [];
}
if (!Array.isArray(tracks)) {
return [];
}
return tracks.filter(
(
track // ensure required fields are present
) =>
track.hasOwnProperty("user") &&
track.hasOwnProperty("username") &&
track.hasOwnProperty("date")
);
};
export default class PlaceholderService extends Service { export default class PlaceholderService extends Service {
name = "PlaceholderService"; name = "PlaceholderService";
register() { register() {
this.app.PmPlugins.add(PLUGIN_KEY, placeholderPlugin(PLUGIN_KEY)); this.app.PmPlugins.add(PLUGIN_KEY, placeholderPlugin(PLUGIN_KEY));
const createNode = this.container.get("CreateNode");
createNode({
paragraph: {
group: "block",
content: "inline*",
attrs: {
class: { default: "paragraph" },
track: { default: [] }
},
parseDOM: {
tag: "p.paragraph",
getAttrs(hook, next) {
Object.assign(hook, {
class: hook.dom.getAttribute("class")
});
next();
}
},
toDOM(hook, next) {
const attrs = { class: hook.node.attrs.class };
hook.value = ["p", attrs, 0];
next();
}
}
});
createNode({
paragraph: {
group: "block",
content: "inline*",
attrs: {
track: { default: [] }
},
parseDOM: {
tag: "p.paragraph",
getAttrs(hook, next) {
Object.assign(hook, {
track: parseTracks(hook.dom.dataset.track)
});
next();
}
},
toDOM(hook, next) {
const attrs = blockLevelToDOM(hook.node);
Object.assign(hook.value[1], {
"data-track": JSON.stringify(hook.node.attrs.track)
});
next();
}
}
});
} }
} }
import ParseRule from "./ParseRule";
import Middleware from "../lib/Middleware";
export default class Mark {
name = "";
importer = {};
inline = false;
group = "";
content = "";
draggable = false;
_attrs = {};
_parseRules = [];
constructor(name) {
this.name = name;
this.importer = new Middleware();
}
fromJSON(config) {
for (let key in config) {
let value = config[key];
this[key] = value;
}
}
set toDOM(value) {
this.importer.use(value);
}
set attrs(value) {
Object.assign(this._attrs, value);
}
set parseDOM(value) {
let parseRule = this._parseRules.find(
parseRule => parseRule.tag === value.tag
);
if (!parseRule) {
parseRule = new ParseRule(value);
this._parseRules.push(parseRule);
}
parseRule.addStack(value.getAttrs);
}
toJSON() {
const importer = this.importer;
return {
inline: this.inline,
group: this.group,
content: this.content,
draggable: this.draggable,
attrs: this._attrs,
parseDOM: this._parseRules.map(rule => rule.combineRules()),
toDOM: node => {
let hooks = {};
importer.go({ node }, hook => {
hooks = hook;
});
return hooks.value;
}
};
}
}
import ParseRule from "./ParseRule";
import Middleware from "../lib/Middleware";
export default class Node {
name = "";
importer = {};
inline = false;
group = "";
content = "";
draggable = false;
_attrs = {};
_parseRules = [];
constructor(name) {
this.name = name;
this.importer = new Middleware();
}
fromJSON(config) {
for (let key in config) {
let value = config[key];
this[key] = value;
}
}
set toDOM(value) {
this.importer.use(value);
}
set attrs(value) {
Object.assign(this._attrs, value);
}
set parseDOM(value) {
let parseRule = this._parseRules.find(
parseRule => parseRule.tag === value.tag
);
if (!parseRule) {
parseRule = new ParseRule(value);
this._parseRules.push(parseRule);
}
parseRule.addStack(value.getAttrs);
}
toJSON() {
const importer = this.importer;
return {
inline: this.inline,
group: this.group,
content: this.content,
draggable: this.draggable,
attrs: this._attrs,
parseDOM: this._parseRules.map(rule => rule.combineRules()),
toDOM: node => {
let hooks = {};
importer.go({ node }, hook => {
hooks = hook;
});
return hooks.value;
}
};
}
}
import { omit } from "lodash";
import Middleware from "../lib/Middleware";
export default class ParseRule {
tag = "";
exporter = {};
constructor({ getAttrs, tag }) {
this.tag = tag;
this.exporter = new Middleware();
this.addStack(getAttrs);
}
addStack(getAttrs) {
this.exporter.use(getAttrs);
}
parseSchema(exporter) {
return {
tag: this.tag,
getAttrs(dom) {
let hooks = {};
exporter.go({ dom }, hook => {
hooks = hook;
});
return omit(hooks, ["dom"]);
}
};
}
combineRules() {
const exporter = this.exporter;
return this.parseSchema(exporter);
}
}
import Node from "./Node";
import Mark from "./Mark";
import { EditoriaSchema } from "wax-prosemirror-schema";
import { injectable } from "inversify";
@injectable()
export default class Schema {
_nodes = {};
_marks = {};
has(instance) {
if (instance instanceof Node) {
return this._nodes[instance.name] ? this._nodes[instance.name] : false;
}
if (instance instanceof Mark) {
return this._marks[instance.name] ? this._marks[instance.name] : false;
}
}
addSchema(instance) {
if (instance instanceof Node) {
return this._nodes[instance.name]
? this._nodes[instance.name]
: Object.assign(this._nodes, {
[instance.name]: instance
});
}
if (instance instanceof Mark) {
return this._marks[instance.name]
? this._marks[instance.name]
: Object.assign(this._marks, {
[instance.name]: instance
});
}
}
getSchema() {
/* this is temporally until all of the packages moved to schemas */
const nodes = EditoriaSchema.nodes;
const marks = EditoriaSchema.marks;
for (let index in this._nodes) {
nodes[index] = this._nodes[index].toJSON();
}
for (let index in this._marks) {
marks[index] = this._marks[index].toJSON();
}
return {
nodes,
marks
};
}
}
import Service from "wax-prosemirror-core/src/services/Service";
import Schema from "./Schema";
import Node from "./Node";
export default class SchemaService extends Service {
name = "SchemaService";
boot() {}
register() {
this.container
.bind("Schema")
.to(Schema)
.inSingletonScope();
this.container.bind("CreateNode").toFactory(context => {
return schemaConfig => {
const schema = context.container.get("Schema");
const name = Object.keys(schemaConfig)[0];
const config = schemaConfig[name];
const node = new Node(name);
let nd = {};
if ((nd = schema.has(node))) {
nd.fromJSON(config);
return nd;
} else {
node.fromJSON(config);
schema.addSchema(node);
return node;
}
};
});
this.container.bind("CreateMark").toFactory(context => {
return schemaConfig => {
const schema = context.container.get("Schema");
const name = Object.keys(schemaConfig)[0];
const config = schemaConfig[name];
const mark = new Mark(name);
let mr = {};
if ((mr = schema.has(mark))) {
mr.fromJSON(config);
return mr;
} else {
mark.fromJSON(config);
schema.addSchema(mark);
return mark;
}
};
});
}
}
export default class Middleware {
constructor() {
// Array prototype last
if (!Array.prototype.last) {
Array.prototype.last = function() {
return this[this.length - 1];
};
}
// Array prototype reduceOneRight
if (!Array.prototype.reduceOneRight) {
Array.prototype.reduceOneRight = function() {
return this.slice(0, -1);
};
}
}
use(fn) {
this.go = (stack => (...args) =>
stack(...args.reduceOneRight(), () => {
let _next = args.last();
fn.apply(this, [
...args.reduceOneRight(),
_next.bind.apply(_next, [null, ...args.reduceOneRight()])
]);
}))(this.go);
}
go(...args) {
let _next = args.last();
_next.apply(this, args.reduceOneRight());
}
}
...@@ -65,7 +65,6 @@ const nodes = { ...@@ -65,7 +65,6 @@ const nodes = {
{ {
tag: "p[data-track]", tag: "p[data-track]",
getAttrs(dom) { getAttrs(dom) {
debugger;
return { return {
track: parseTracks(dom.dataset.track) track: parseTracks(dom.dataset.track)
}; };
...@@ -74,8 +73,6 @@ const nodes = { ...@@ -74,8 +73,6 @@ const nodes = {
{ {
tag: "p.paragraph", tag: "p.paragraph",
getAttrs(dom) { getAttrs(dom) {
console.log(dom.getAttribute("class"));
debugger;
return { return {
class: dom.getAttribute("class") class: dom.getAttribute("class")
}; };
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment