aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/util/ProsemirrorExampleTransfer.ts82
-rw-r--r--src/client/util/RichTextSchema.tsx102
-rw-r--r--src/client/util/TooltipTextMenu.tsx34
4 files changed, 125 insertions, 95 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 124faf266..ec731da84 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -204,4 +204,4 @@ export class DocumentManager {
}
}
}
-Scripting.addGlobal(function focus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)) }) \ No newline at end of file
+Scripting.addGlobal(function focus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, true)); }); \ No newline at end of file
diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index 3cdfba59a..3979d8a49 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -79,66 +79,71 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
bind("Mod-s", TooltipTextMenu.insertStar);
+ let nodeTypeMark = (depth: number) => depth === 2 ? "indent2" : depth === 4 ? "indent3" : depth === 6 ? "indent4" : "indent1";
- let levelMark = (depth: number) => {
- let p10 = schema.marks.pFontSize.create({ fontSize: 10 });
- let p14 = schema.marks.pFontSize.create({ fontSize: 14 });
- let p18 = schema.marks.pFontSize.create({ fontSize: 18 });
- let p24 = schema.marks.pFontSize.create({ fontSize: 24 });
- return depth == 0 ? p24 : depth == 2 ? p18 : depth == 4 ? p14 : p10;
- }
let bulletFunc = (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
var ref = state.selection;
var range = ref.$from.blockRange(ref.$to);
var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
let depth = range && range.depth ? range.depth : 0;
- let nodeType = depth == 2 ? schema.nodes.cap_alphabet_list : depth == 4 ? schema.nodes.roman_list : depth == 6 ? schema.nodes.alphabet_list : schema.nodes.ordered_list;
- let nodeTypeMark = depth == 2 ? schema.marks.mcap_alphabet_list : depth == 4 ? schema.marks.mroman_list : depth == 6 ? schema.marks.malphabet_list : schema.marks.mordered_list;
- let created = levelMark(depth);
- if (!sinkListItem(nodeType /*schema.nodes.list_item */)(state, (tx2: Transaction) => {
+ if (!sinkListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
const resolvedPos = tx2.doc.resolve(range!.start);
- let ns = new NodeSelection(resolvedPos);
- let tx3 = tx2.addMark(ns.from - 1, ns.to, created).addMark(ns.from - 1, ns.to, nodeTypeMark as any).setSelection(TextSelection.create(tx2.doc, ns.to - (depth == 0 ? 3 : 1)));
- marks && tx3.ensureMarks([...marks, created]);
- marks && tx3.setStoredMarks([...marks, created]);
-
- dispatch(tx3);
+ let path = (resolvedPos as any).path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = nodeTypeMark(depth);
+ break;
+ }
+ }
+ marks && tx2.ensureMarks([...marks]);
+ marks && tx2.setStoredMarks([...marks]);
+ dispatch(tx2);
})) {
let sxf = state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end));
let newstate = state.applyTransaction(sxf);
- if (!wrapInList(nodeType)(newstate.state, (tx2: Transaction) => {
- const resolvedPos = tx2.doc.resolve(range!.start);
- let ns = new TextSelection(resolvedPos, tx2.doc.resolve(range!.end + 1)); // new NodeSelection(resolvedPos);
- let tx3 = tx2.setSelection(ns).removeMark(ns.from, ns.to, created).addMark(ns.from, ns.to, created).setSelection(TextSelection.create(tx2.doc, ns.to));
- let tx4 = depth > 0 ? tx3.insertText(" ").setSelection(TextSelection.create(tx2.doc, ns.to - 2, ns.to + 2)).deleteSelection() : tx3;
- marks && tx4.ensureMarks([...marks, created]);
- marks && tx4.setStoredMarks([...marks, created]);
-
- dispatch(tx4);
+ if (!wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => {
+ const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
+ let path = (resolvedPos as any).path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = nodeTypeMark(depth);
+ break;
+ }
+ }
+ // when promoting to a list, assume list will format things so don't copy the stored marks.
+ // marks && tx2.ensureMarks([...marks]);
+ // marks && tx2.setStoredMarks([...marks]);
+
+ dispatch(tx2);
})) {
console.log("bullet fail");
}
}
- }
- bind("Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => bulletFunc(state, dispatch));
+ };
+
+ bind("Tab", bulletFunc);
bind("Shift-Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
var ref = state.selection;
var range = ref.$from.blockRange(ref.$to);
var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
- let created = levelMark(range && range.depth ? range.depth - 4 : 0);
+ let depth = range && range.depth > 3 ? range.depth - 4 : 0;
liftListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
try {
const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
- let nodeIndex = resolvedPos.pos - (resolvedPos.nodeBefore && resolvedPos.nodeBefore.type.name === "text" ? resolvedPos.nodeBefore!.nodeSize : 0);
- let ns = new NodeSelection(tx2.doc.resolve(nodeIndex));
- if (resolvedPos.nodeAfter && resolvedPos.nodeAfter.type.name === "list_item")
- ns = new NodeSelection(tx2.doc.resolve(nodeIndex + 1));
- let tx3 = tx2.setSelection(ns).removeMark(ns.from, ns.to, created).addMark(ns.from, ns.to, created).setSelection(TextSelection.create(tx2.doc, ns.to));
- marks && tx3.ensureMarks([...marks, created]);
- marks && tx3.setStoredMarks([...marks, created]);
- dispatch(tx3);
+
+ let path = (resolvedPos as any).path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = nodeTypeMark(depth);
+ break;
+ }
+ }
+
+ marks && tx2.ensureMarks([...marks]);
+ marks && tx2.setStoredMarks([...marks]);
+ dispatch(tx2);
} catch (e) {
dispatch(tx2);
}
@@ -155,7 +160,8 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
if (!splitBlockKeepMarks(state, (tx3: Transaction) => {
marks && tx3.ensureMarks(marks);
marks && tx3.setStoredMarks(marks);
- if (!liftListItem(schema.nodes.list_item)(state, (tx4: Transaction) => dispatch(tx4))) {
+ if (!liftListItem(schema.nodes.list_item)(state, dispatch as ((tx: Transaction<Schema<any, any>>) => void))
+ ) {
dispatch(tx3);
}
})) {
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index f128162c2..a642ee46c 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -1,6 +1,7 @@
import { DOMOutputSpecArray, MarkSpec, Node, NodeSpec, Schema, Slice } from "prosemirror-model";
import { bulletList, listItem, orderedList } from 'prosemirror-schema-list';
import { TextSelection } from "prosemirror-state";
+import { Doc } from "../../new_fields/Doc";
const pDOM: DOMOutputSpecArray = ["p", 0], blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"],
preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0];
@@ -175,43 +176,17 @@ export const nodes: { [index: string]: NodeSpec } = {
content: 'list_item+',
group: 'block',
attrs: {
- bulletStyle: { default: "decimal" },
+ bulletStyle: { default: "" },
+ mapStyle: { default: "decimal" }
},
toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
- }
- },
- alphabet_list: {
- ...orderedList,
- content: 'list_item+',
- group: 'block',
- attrs: {
- bulletStyle: { default: "lower-alpha" },
- },
- toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
- }
- },
- cap_alphabet_list: {
- ...orderedList,
- content: 'list_item+',
- group: 'block',
- attrs: {
- bulletStyle: { default: "upper-alpha" },
- },
- toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
- }
- },
- roman_list: {
- ...orderedList,
- content: 'list_item+',
- group: 'block',
- attrs: {
- bulletStyle: { default: "lower-roman" },
- },
- toDOM(node: Node<any>) {
- return ['ol', { style: `list-style: ${node.attrs.bulletStyle}` }, 0]
+ const bs = node.attrs.bulletStyle;
+ const decMap = bs === "indent1" ? "decimal" : bs === "indent2" ? "decimal2" : bs === "indent3" ? "decimal3" : bs === "indent4" ? "decimal4" : "";
+ const multiMap = bs === "indent1" ? "decimal" : bs === "indent2" ? "upper-alpha" : bs === "indent3" ? "lower-roman" : bs === "indent4" ? "lower-alpha" : "";
+ let map = node.attrs.mapStyle === "decimal" ? decMap : multiMap;
+ for (let i = 0; i < node.childCount; i++) node.child(i).attrs.className = map;
+ return ['ol', { class: `${map}-ol`, style: `list-style: none;` }, 0];
+ //return ['ol', { class: `${node.attrs.bulletStyle}`, style: `list-style: ${node.attrs.bulletStyle};`, 0]
}
},
//this doesn't currently work for some reason
@@ -220,9 +195,10 @@ export const nodes: { [index: string]: NodeSpec } = {
content: 'list_item+',
group: 'block',
// parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
- // toDOM() { return ['ol', {
- // style: 'list-type: hebrew'
- // }] }
+ toDOM(node: Node<any>) {
+ for (let i = 0; i < node.childCount; i++) node.child(i).attrs.className = "";
+ return ['ul', 0];
+ }
},
//bullet_list: {
@@ -234,8 +210,14 @@ export const nodes: { [index: string]: NodeSpec } = {
//select: state => true,
// },
list_item: {
+ attrs: {
+ className: { default: "" }
+ },
...listItem,
- content: 'paragraph block*'
+ content: 'paragraph block*',
+ toDOM(node: any) {
+ return ["li", { class: node.attrs.className }, 0];
+ }
},
};
@@ -267,7 +249,7 @@ export const marks: { [index: string]: MarkSpec } = {
// :: MarkSpec An emphasis mark. Rendered as an `<em>` element.
// Has parse rules that also match `<i>` and `font-style: italic`.
em: {
- parseDOM: [{ tag: "i" }, { tag: "em" }, { style: "font-style=italic" }],
+ parseDOM: [{ tag: "i" }, { tag: "em" }, { style: "font-style: italic" }],
toDOM() { return emDOM; }
},
@@ -319,13 +301,15 @@ export const marks: { [index: string]: MarkSpec } = {
toDOM: () => ['sup']
},
- malphabet_list: {
- },
- mcap_alphabet_list: {
- },
- mroman_list: {
- },
- mo_list: {
+ mbulletType: {
+ attrs: {
+ bulletType: { default: "decimal" }
+ },
+ toDOM(node: any) {
+ return ['span', {
+ style: `background: ${node.attrs.bulletType === "decimal" ? "yellow" : node.attrs.bulletType === "upper-alpha" ? "blue" : "green"}`
+ }];
+ }
},
highlight: {
@@ -346,6 +330,28 @@ export const marks: { [index: string]: MarkSpec } = {
}
},
+ // the id of the user who entered the text
+ user_mark: {
+ attrs: {
+ userid: { default: "" },
+ hide_users: { default: [] },
+ opened: { default: true },
+ modified: { default: "when?" }
+ },
+ group: "inline",
+ inclusive: false,
+ toDOM(node: any) {
+ let hideUsers = node.attrs.hide_users;
+ let hidden = hideUsers.indexOf(node.attrs.userid) !== -1 || (hideUsers.length === 0 && node.attrs.userid !== Doc.CurrentUserEmail);
+ return hidden ?
+ (node.attrs.opened ?
+ ['span', { class: "userMarkOpen" }, 0] :
+ ['span', { class: "userMark" }, ['span', { style: "font-size:2" }, 0]]
+ ) :
+ ['span', 0];
+ }
+ },
+
// :: MarkSpec Code font mark. Represented as a `<code>` element.
code: {
@@ -599,6 +605,8 @@ export class SummarizedView {
attrs.textslice = newSelection.content().toJSON();
view.dispatch(view.state.tr.setNodeMarkup(y, undefined, attrs));
view.dispatch(view.state.tr.setSelection(newSelection).deleteSelection(view.state, () => { }));
+ let marks = view.state.storedMarks.filter((m: any) => m.type !== view.state.schema.marks.highlight);
+ view.state.storedMarks = marks;
self._collapsed.textContent = "㊉";
} else {
// node.attrs.visibility = !node.attrs.visibility;
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 77396c829..e979e6cde 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -28,11 +28,11 @@ export class TooltipTextMenu {
private view: EditorView;
private fontStyles: MarkType[];
private fontSizes: MarkType[];
- private listTypes: NodeType[];
+ private listTypes: (NodeType | any)[];
private editorProps: FieldViewProps & FormattedTextBoxProps;
private fontSizeToNum: Map<MarkType, number>;
private fontStylesToName: Map<MarkType, string>;
- private listTypeToIcon: Map<NodeType, string>;
+ private listTypeToIcon: Map<NodeType | any, string>;
//private link: HTMLAnchorElement;
private wrapper: HTMLDivElement;
private extras: HTMLDivElement;
@@ -179,10 +179,8 @@ export class TooltipTextMenu {
//list types
this.listTypeToIcon = new Map();
this.listTypeToIcon.set(schema.nodes.bullet_list, ":");
- this.listTypeToIcon.set(schema.nodes.ordered_list, "1)");
- this.listTypeToIcon.set(schema.nodes.alphabet_list, "a)");
- this.listTypeToIcon.set(schema.nodes.cap_alphabet_list, "A)");
- this.listTypeToIcon.set(schema.nodes.roman_list, "i.");
+ this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "decimal" }), "1.1");
+ this.listTypeToIcon.set(schema.nodes.ordered_list.create({ mapStyle: "multi" }), "1.A");
// this.listTypeToIcon.set(schema.nodes.bullet_list, "⬜");
this.listTypes = Array.from(this.listTypeToIcon.keys());
@@ -515,10 +513,28 @@ export class TooltipTextMenu {
//remove all node typeand apply the passed-in one to the selected text
changeToNodeType(nodeType: NodeType | undefined, view: EditorView) {
- //remove old
- liftListItem(schema.nodes.list_item)(view.state, view.dispatch);
- if (nodeType) { //add new
+ //remove oldif (nodeType) { //add new
+ if (nodeType === schema.nodes.bullet_list) {
wrapInList(nodeType)(view.state, view.dispatch);
+ } else {
+ var ref = view.state.selection;
+ var range = ref.$from.blockRange(ref.$to);
+ var marks = view.state.storedMarks || (view.state.selection.$to.parentOffset && view.state.selection.$from.marks());
+ wrapInList(schema.nodes.ordered_list)(view.state, (tx2: any) => {
+ const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
+ let path = resolvedPos.path;
+ for (let i = path.length - 1; i > 0; i--) {
+ if (path[i].type === schema.nodes.ordered_list) {
+ path[i].attrs.bulletStyle = "indent1";
+ path[i].attrs.mapStyle = (nodeType as any).attrs.mapStyle;
+ break;
+ }
+ }
+ marks && tx2.ensureMarks([...marks]);
+ marks && tx2.setStoredMarks([...marks]);
+
+ view.dispatch(tx2);
+ });
}
}