From 939074601016a674d6a01922bab1383684fce63f Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 25 Aug 2019 22:55:51 -0400
Subject: added sub-bullet types to prosemirror

---
 src/client/util/TooltipTextMenu.tsx | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 4672dd246..7a0c6f8c5 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -172,6 +172,9 @@ export class TooltipTextMenu {
         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.bullet_list, "⬜");
         this.listTypes = Array.from(this.listTypeToIcon.keys());
 
-- 
cgit v1.2.3-70-g09d2


From 094bbd52f2b55f501357a9f6b057042ad7684f27 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 26 Aug 2019 16:58:24 -0400
Subject: playing more with bulleted lists.

---
 src/client/util/ProsemirrorExampleTransfer.ts | 70 +++++++++++++++++++++------
 src/client/util/RichTextRules.ts              |  3 +-
 src/client/util/RichTextSchema.tsx            | 10 +++-
 src/client/util/TooltipTextMenu.tsx           | 10 +++-
 src/client/views/nodes/FormattedTextBox.tsx   | 12 ++---
 5 files changed, 78 insertions(+), 27 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index b928532d6..3cdfba59a 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -2,8 +2,8 @@ import { chainCommands, exitCode, joinDown, joinUp, lift, selectParentNode, setB
 import { redo, undo } from "prosemirror-history";
 import { undoInputRule } from "prosemirror-inputrules";
 import { Schema } from "prosemirror-model";
-import { liftListItem, splitListItem, wrapInList } from "prosemirror-schema-list";
-import { EditorState, Transaction } from "prosemirror-state";
+import { liftListItem, splitListItem, wrapInList, sinkListItem } from "prosemirror-schema-list";
+import { EditorState, Transaction, TextSelection, NodeSelection } from "prosemirror-state";
 import { TooltipTextMenu } from "./TooltipTextMenu";
 
 const mac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
@@ -79,32 +79,72 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
 
     bind("Mod-s", TooltipTextMenu.insertStar);
 
-    bind("Shift-Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
-        var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
-        liftListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
-            marks && tx2.ensureMarks(marks);
-            marks && tx2.setStoredMarks(marks);
-            dispatch(tx2);
-        });
-    });
 
+    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) => {
+            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]);
 
-        if (!wrapInList(nodeType)(state, (tx2: Transaction) => {
-            marks && tx2.ensureMarks(marks);
-            marks && tx2.setStoredMarks(marks);
-            dispatch(tx2);
+            dispatch(tx3);
         })) {
-            console.log("bullet fail");
+            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);
+            })) {
+                console.log("bullet fail");
+            }
         }
     }
     bind("Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => bulletFunc(state, dispatch));
 
+    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);
+        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);
+            } catch (e) {
+                dispatch(tx2);
+            }
+        });
+    });
+
     bind("Enter", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
         var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
         if (!splitListItem(schema.nodes.list_item)(state, (tx3: Transaction) => {
diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts
index 89933650b..8c4c76027 100644
--- a/src/client/util/RichTextRules.ts
+++ b/src/client/util/RichTextRules.ts
@@ -26,7 +26,7 @@ export const inpRules = {
             match => ({ order: +match[1] }),
             (match, node) => node.childCount + node.attrs.order === +match[1]
         ),
-        // 1. ordered list
+        // a. alphabbetical list
         wrappingInputRule(
             /^([a-z]+)\.\s$/,
             schema.nodes.alphabet_list,
@@ -34,7 +34,6 @@ export const inpRules = {
             (match, node) => node.childCount + node.attrs.order === +match[1]
         ),
 
-
         // * bullet list
         wrappingInputRule(/^\s*([-+*])\s$/, schema.nodes.bullet_list),
 
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index a8ce4731c..f128162c2 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -319,6 +319,15 @@ export const marks: { [index: string]: MarkSpec } = {
         toDOM: () => ['sup']
     },
 
+    malphabet_list: {
+    },
+    mcap_alphabet_list: {
+    },
+    mroman_list: {
+    },
+    mo_list: {
+    },
+
     highlight: {
         parseDOM: [{ style: 'color: blue' }],
         toDOM() {
@@ -412,7 +421,6 @@ export const marks: { [index: string]: MarkSpec } = {
         attrs: {
             fontSize: { default: 10 }
         },
-        inclusive: false,
         parseDOM: [{ style: 'font-size: 10px;' }],
         toDOM: (node) => ['span', {
             style: `font-size: ${node.attrs.fontSize}px;`
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 7a0c6f8c5..77396c829 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -165,7 +165,15 @@ export class TooltipTextMenu {
         this.fontSizeToNum.set(schema.marks.p48, 48);
         this.fontSizeToNum.set(schema.marks.p72, 72);
         this.fontSizeToNum.set(schema.marks.pFontSize, 10);
-        this.fontSizeToNum.set(schema.marks.pFontSize, 10);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 12);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 14);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 16);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 18);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 20);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 24);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 32);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 48);
+        // this.fontSizeToNum.set(schema.marks.pFontSize, 72);
         this.fontSizes = Array.from(this.fontSizeToNum.keys());
 
         //list types
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d6ba1700a..acfd2a3b8 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -115,7 +115,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
 
     @undoBatch
     public setFontColor(color: string) {
-        let self = this;
         if (this._editorView!.state.selection.from === this._editorView!.state.selection.to) return false;
         if (this._editorView!.state.selection.to - this._editorView!.state.selection.from > this._editorView!.state.doc.nodeSize - 3) {
             this.props.Document.color = color;
@@ -176,15 +175,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             FormattedTextBox._toolTipTextMenu && (FormattedTextBox._toolTipTextMenu.HackToFixTextSelectionGlitch = true);
             this._editorView.updateState(state);
             FormattedTextBox._toolTipTextMenu && (FormattedTextBox._toolTipTextMenu.HackToFixTextSelectionGlitch = false);
-            if (state.selection.empty && FormattedTextBox._toolTipTextMenu) {
-                const marks = tx.storedMarks;
-                if (marks) { FormattedTextBox._toolTipTextMenu.mark_key_pressed(marks); }
+            if (state.selection.empty && FormattedTextBox._toolTipTextMenu && tx.storedMarks) {
+                FormattedTextBox._toolTipTextMenu.mark_key_pressed(tx.storedMarks);
             }
 
             this._applyingChange = true;
-            const fieldkey = "preview";
-            if (this.extensionDoc) this.extensionDoc.text = state.doc.textBetween(0, state.doc.content.size, "\n\n");
-            if (this.extensionDoc) this.extensionDoc.lastModified = new DateField(new Date(Date.now()));
+            this.extensionDoc && (this.extensionDoc.text = state.doc.textBetween(0, state.doc.content.size, "\n\n"));
+            this.extensionDoc && (this.extensionDoc.lastModified = new DateField(new Date(Date.now())));
             this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()));
             this._applyingChange = false;
             let title = StrCast(this.dataDoc.title);
@@ -198,7 +195,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
 
     public highlightSearchTerms = (terms: String[]) => {
         if (this._editorView && (this._editorView as any).docView) {
-            const fieldkey = "preview";
             const doc = this._editorView.state.doc;
             const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight);
             doc.nodesBetween(0, doc.content.size, (node: ProsNode, pos: number, parent: ProsNode, index: number) => {
-- 
cgit v1.2.3-70-g09d2


From e13dc44532ea5f94bdc13a2103bc4a00438ee617 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 27 Aug 2019 01:29:35 -0400
Subject: simplified things.

---
 src/client/util/ProsemirrorExampleTransfer.ts | 43 ++++++++++-----------------
 src/client/util/RichTextSchema.tsx            | 33 --------------------
 src/client/util/TooltipTextMenu.tsx           |  3 --
 3 files changed, 15 insertions(+), 64 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index 052fb0c6d..d602ce4a1 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -84,35 +84,28 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
         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 = schema.marks.mbulletType.create({ bulletType: depth == 2 ? "upper-alpha" : depth == 4 ? "lower-roman" : depth == 6 ? "lower-alpha" : "decimal" });
+        let nodeTypeMark = depth == 2 ? "upper-alpha" : depth == 4 ? "lower-roman" : depth == 6 ? "lower-alpha" : "decimal";
         if (!sinkListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
             const resolvedPos = tx2.doc.resolve(range!.start);
 
             let path = (resolvedPos as any).path as any;
             for (let i = path.length - 1; i > 0; i--) {
                 if (path[i].type === schema.nodes.ordered_list) {
-                    path[i].attrs.bulletStyle = (nodeTypeMark as any).attrs.bulletType;
+                    path[i].attrs.bulletStyle = nodeTypeMark;
                     break;
                 }
             }
-            let ns = new NodeSelection(resolvedPos);
-            let tx3 = tx2.setSelection(TextSelection.create(tx2.doc, ns.to - (depth == 0 ? 3 : 1)));
-            marks && tx3.ensureMarks([...marks]);
-            marks && tx3.setStoredMarks([...marks]);
-            dispatch(tx3);
+            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).setSelection(TextSelection.create(tx2.doc, ns.to));
-                let tx4 = tx3;
-                marks && tx4.ensureMarks([...marks]);
-                marks && tx4.setStoredMarks([...marks]);
-
-                dispatch(tx4);
+            if (!wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => {
+                marks && tx2.ensureMarks([...marks]);
+                marks && tx2.setStoredMarks([...marks]);
+
+                dispatch(tx2);
             })) {
                 console.log("bullet fail");
             }
@@ -125,28 +118,22 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
         var range = ref.$from.blockRange(ref.$to);
         var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
         let depth = range && range.depth > 3 ? range.depth - 4 : 0;
-        let nodeTypeMark = schema.marks.mbulletType.create({ bulletType: depth == 2 ? "upper-alpha" : depth == 4 ? "lower-roman" : depth == 6 ? "lower-alpha" : "decimal" });
+        let nodeTypeMark = depth == 2 ? "upper-alpha" : depth == 4 ? "lower-roman" : depth == 6 ? "lower-alpha" : "decimal";
         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 path = (resolvedPos as any).path as any;
                 for (let i = path.length - 1; i > 0; i--) {
                     if (path[i].type === schema.nodes.ordered_list) {
-                        path[i].attrs.bulletStyle = (nodeTypeMark as any).attrs.bulletType;
+                        path[i].attrs.bulletStyle = nodeTypeMark;
                         break;
                     }
                 }
 
-                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).setSelection(TextSelection.create(tx2.doc, ns.to));
-
-                marks && tx3.ensureMarks([...marks]);
-                marks && tx3.setStoredMarks([...marks]);
-                dispatch(tx3);
+                marks && tx2.ensureMarks([...marks]);
+                marks && tx2.setStoredMarks([...marks]);
+                dispatch(tx2);
             } catch (e) {
                 dispatch(tx2);
             }
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 26960e889..255f4a60d 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -182,39 +182,6 @@ export const nodes: { [index: string]: NodeSpec } = {
             return ['ol', { style: `list-style: ${node.attrs.bulletStyle}; font-size: ${fsize}` }, 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]
-        }
-    },
     //this doesn't currently work for some reason
     bullet_list: {
         ...bulletList,
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 77396c829..7f6ba3aac 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -180,9 +180,6 @@ export class TooltipTextMenu {
         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.bullet_list, "⬜");
         this.listTypes = Array.from(this.listTypeToIcon.keys());
 
-- 
cgit v1.2.3-70-g09d2


From 1fbf7d7e10bb4dfa7e3a323ee0641d7bbf97b6a8 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 27 Aug 2019 23:24:18 -0400
Subject: fixed several lint errors, and minor issues with bullets

---
 src/client/util/DocumentManager.ts                 |  2 +-
 src/client/util/ProsemirrorExampleTransfer.ts      | 17 ++++-----
 src/client/util/RichTextSchema.tsx                 | 13 ++++---
 src/client/util/TooltipTextMenu.tsx                | 31 ++++++++++++----
 src/client/views/DocumentDecorations.tsx           |  2 +-
 .../views/collections/CollectionTreeView.tsx       | 42 +++++++++++-----------
 .../views/collections/CollectionViewChromes.tsx    |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  6 ++--
 8 files changed, 71 insertions(+), 44 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

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 8b6936748..12ad28199 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -79,8 +79,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
 
     bind("Mod-s", TooltipTextMenu.insertStar);
 
-    // let nodeTypeMark = depth == 2 ? "upper-alpha" : depth == 4 ? "lower-roman" : depth == 6 ? "lower-alpha" : "decimal";
-    let nodeTypeMark = (depth: number) => { return depth == 2 ? "decimal2" : depth == 4 ? "decimal3" : depth == 6 ? "decimal4" : "decimal" }
+    let nodeTypeMark = (depth: number) => depth === 2 ? "indent2" : depth === 4 ? "indent3" : depth === 6 ? "indent4" : "indent1";
 
     let bulletFunc = (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
         var ref = state.selection;
@@ -90,7 +89,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
         if (!sinkListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
             const resolvedPos = tx2.doc.resolve(range!.start);
 
-            let path = (resolvedPos as any).path as any;
+            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);
@@ -105,7 +104,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
             let newstate = state.applyTransaction(sxf);
             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 as any;
+                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);
@@ -120,8 +119,9 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
                 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;
@@ -132,7 +132,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
             try {
                 const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
 
-                let path = (resolvedPos as any).path as any;
+                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);
@@ -159,7 +159,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 76c45e6c1..4e18f410d 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -177,10 +177,15 @@ export const nodes: { [index: string]: NodeSpec } = {
         group: 'block',
         attrs: {
             bulletStyle: { default: "" },
+            mapStyle: { default: "decimal" }
         },
         toDOM(node: Node<any>) {
-            for (let i = 0; i < node.childCount; i++) node.child(i).attrs.className = node.attrs.bulletStyle;
-            return ['ol', { class: `${node.attrs.bulletStyle}-ol`, style: `list-style: none;` }, 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]
         }
     },
@@ -192,7 +197,7 @@ export const nodes: { [index: string]: NodeSpec } = {
         // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }],
         toDOM(node: Node<any>) {
             for (let i = 0; i < node.childCount; i++) node.child(i).attrs.className = "";
-            return ['ul', 0]
+            return ['ul', 0];
         }
     },
 
@@ -302,7 +307,7 @@ export const marks: { [index: string]: MarkSpec } = {
         },
         toDOM(node: any) {
             return ['span', {
-                style: `background: ${node.attrs.bulletType == "decimal" ? "yellow" : node.attrs.bulletType === "upper-alpha" ? "blue" : "green"}`
+                style: `background: ${node.attrs.bulletType === "decimal" ? "yellow" : node.attrs.bulletType === "upper-alpha" ? "blue" : "green"}`
             }];
         }
     },
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 7f6ba3aac..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,7 +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.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());
 
@@ -512,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);
+            });
         }
     }
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index e93893586..203227241 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -201,7 +201,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     }
 
     @observable _forceUpdate = 0;
-    _lastBox = { x: 0, y: 0, r: 0, b: 0 }
+    _lastBox = { x: 0, y: 0, r: 0, b: 0 };
     @computed
     get Bounds(): { x: number, y: number, b: number, r: number } {
         let x = this._forceUpdate;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 04133fb5b..50f03005c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -432,26 +432,28 @@ class TreeView extends React.Component<TreeViewProps> {
         }
 
         let ascending = Cast(containingCollection.sortAscending, "boolean", null);
-        if (ascending !== undefined) docs.sort(function (a, b): 1 | -1 {
-            let descA = ascending ? b : a;
-            let descB = ascending ? a : b;
-            let first = descA.title;
-            let second = descB.title;
-            // TODO find better way to sort how to sort..................
-            if (typeof first === 'number' && typeof second === 'number') {
-                return (first - second) > 0 ? 1 : -1;
-            }
-            if (typeof first === 'string' && typeof second === 'string') {
-                return first > second ? 1 : -1;
-            }
-            if (typeof first === 'boolean' && typeof second === 'boolean') {
-                // if (first === second) { // bugfixing?: otherwise, the list "flickers" because the list is resorted during every load
-                //     return Number(descA.x) > Number(descB.x) ? 1 : -1;
-                // }
-                return first > second ? 1 : -1;
-            }
-            return ascending ? 1 : -1;
-        });
+        if (ascending !== undefined) {
+            docs.sort(function (a, b): 1 | -1 {
+                let descA = ascending ? b : a;
+                let descB = ascending ? a : b;
+                let first = descA.title;
+                let second = descB.title;
+                // TODO find better way to sort how to sort..................
+                if (typeof first === 'number' && typeof second === 'number') {
+                    return (first - second) > 0 ? 1 : -1;
+                }
+                if (typeof first === 'string' && typeof second === 'string') {
+                    return first > second ? 1 : -1;
+                }
+                if (typeof first === 'boolean' && typeof second === 'boolean') {
+                    // if (first === second) { // bugfixing?: otherwise, the list "flickers" because the list is resorted during every load
+                    //     return Number(descA.x) > Number(descB.x) ? 1 : -1;
+                    // }
+                    return first > second ? 1 : -1;
+                }
+                return ascending ? 1 : -1;
+            });
+        }
 
         let rowWidth = () => panelWidth() - 20;
         return docs.map((child, i) => {
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 4b3f7c87e..c897af17e 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -53,7 +53,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     };
     _viewCommand = {
         title: "restore view", script: "this.target.panX = this.restoredPanX; this.target.panY = this.restoredPanY; this.target.scale = this.restoredScale;", params: ["target"],
-        immediate: (draggedDocs: Doc[]) => { this.props.CollectionView.props.Document.panX = 0; this.props.CollectionView.props.Document.panY = 0; this.props.CollectionView.props.Document.scale = 1 },
+        immediate: (draggedDocs: Doc[]) => { this.props.CollectionView.props.Document.panX = 0; this.props.CollectionView.props.Document.panY = 0; this.props.CollectionView.props.Document.scale = 1; },
         initialize: (button: Doc) => { button.restoredPanX = this.props.CollectionView.props.Document.panX; button.restoredPanY = this.props.CollectionView.props.Document.panY; button.restoredScale = this.props.CollectionView.props.Document.scale; }
     };
     _freeform_commands = [this._contentCommand, this._templateCommand, this._viewCommand];
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index ba558a0b2..36740fc66 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -331,8 +331,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                     keymap(buildKeymap(schema)),
                     keymap(baseKeymap),
                 ]
-        }
-    };
+        };
+    }
 
     @action
     rebuildEditor() {
@@ -776,7 +776,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             SelectionManager.DeselectAll();
         }
         e.stopPropagation();
-        if (e.key === "Tab") {
+        if (e.key === "Tab" || e.key === "Enter") { // bullets typically change "levels" when tab or enter is used.  sometimes backspcae, so maybe that should be added.
             e.preventDefault();
             setTimeout(() => { // force re-rendering of bullet numbers that may have had their bullet labels change.  (Our prosemirrior code re-"marks" the changed bullets, but nothing causes the Dom to be re-rendered which is where the nubering takes place)
                 SelectionManager.DeselectAll();
-- 
cgit v1.2.3-70-g09d2


From 5f39a01998e5ee60eb6b796a5cd6b11fc680ceee Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 30 Aug 2019 13:04:40 -0400
Subject: cleanup of outline mode text

---
 src/client/util/ProsemirrorExampleTransfer.ts | 96 +++++++++++++--------------
 src/client/util/RichTextSchema.tsx            |  6 +-
 src/client/util/TooltipLinkingMenu.tsx        | 20 +-----
 src/client/util/TooltipTextMenu.tsx           |  4 +-
 src/client/util/prosemirrorPatches.js         | 62 +++++++++++++++++
 5 files changed, 117 insertions(+), 71 deletions(-)
 create mode 100644 src/client/util/prosemirrorPatches.js

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index 3979d8a49..4af2cf58f 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -2,7 +2,8 @@ import { chainCommands, exitCode, joinDown, joinUp, lift, selectParentNode, setB
 import { redo, undo } from "prosemirror-history";
 import { undoInputRule } from "prosemirror-inputrules";
 import { Schema } from "prosemirror-model";
-import { liftListItem, splitListItem, wrapInList, sinkListItem } from "prosemirror-schema-list";
+import { liftListItem, } from "./prosemirrorPatches.js";
+import { splitListItem, wrapInList, sinkListItem } from "prosemirror-schema-list";
 import { EditorState, Transaction, TextSelection, NodeSelection } from "prosemirror-state";
 import { TooltipTextMenu } from "./TooltipTextMenu";
 
@@ -79,75 +80,73 @@ 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 updateBullets = (tx2: Transaction, refStart: number, delta: number) => {
+        for (let i = refStart; i > 0; i--) {
+            let testPos = tx2.doc.nodeAt(i);
+            if (testPos && testPos.type === schema.nodes.list_item) {
+                let start = i;
+                let preve = i > 0 && tx2.doc.nodeAt(start - 1);
+                if (preve && preve.type === schema.nodes.ordered_list) {
+                    start = start - 1;
+                }
+                let rangeStart = tx2.doc.nodeAt(start);
+                if (rangeStart && rangeStart.type === schema.nodes.ordered_list) {
+                    tx2.setNodeMarkup(start, rangeStart.type, { ...rangeStart.attrs, bulletStyle: rangeStart.attrs.bulletStyle + delta }, rangeStart.marks);
+                }
+                rangeStart && rangeStart.descendants((node: any, offset: any, index: any) => {
+                    if (node.type === schema.nodes.ordered_list) {
+                        tx2.setNodeMarkup(start + offset + 1, node.type, { ...node.attrs, bulletStyle: node.attrs.bulletStyle + delta }, node.marks);
+                    }
+                });
+                break;
+            }
+        }
+    }
 
-    let bulletFunc = (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
+    bind("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 depth = range && range.depth ? range.depth : 0;
         if (!sinkListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
-            const resolvedPos = tx2.doc.resolve(range!.start);
-
-            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;
-                }
-            }
+            updateBullets(tx2, range!.start, 1);
             marks && tx2.ensureMarks([...marks]);
             marks && tx2.setStoredMarks([...marks]);
             dispatch(tx2);
-        })) {
+        })) { // couldn't sink into an existing list, so wrap in a new one
             let sxf = state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end));
             let newstate = state.applyTransaction(sxf);
             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);
+                for (let i = range!.start; i >= 0; i--) {
+                    let rangeStart = tx2.doc.nodeAt(i);
+                    if (rangeStart && rangeStart.type === schema.nodes.ordered_list) {
+                        tx2.setNodeMarkup(i, rangeStart.type, { ...rangeStart.attrs, bulletStyle: 1 }, rangeStart.marks);
                         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]);
-
+                marks && tx2.ensureMarks([...marks]);
+                marks && tx2.setStoredMarks([...marks]);
                 dispatch(tx2);
             })) {
-                console.log("bullet fail");
+                console.log("bullet promote fail");
             }
         }
-    };
-
-    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 range = state.selection.$from.blockRange(state.selection.$to);
         var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
-        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 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);
-            }
-        });
+        let tr = state.tr;
+        updateBullets(tr, range!.start, -1);
+
+        if (!liftListItem(schema.nodes.list_item)(tr, (tx2: Transaction) => {
+            marks && tx2.ensureMarks([...marks]);
+            marks && tx2.setStoredMarks([...marks]);
+            dispatch(tx2);
+        })) {
+            console.log("bullet demote fail");
+        }
     });
 
     bind("Enter", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
@@ -160,8 +159,7 @@ 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, dispatch as ((tx: Transaction<Schema<any, any>>) => void))
-                ) {
+                if (!liftListItem(schema.nodes.list_item)(tx3, 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 a642ee46c..0994f5f6b 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -176,13 +176,13 @@ export const nodes: { [index: string]: NodeSpec } = {
         content: 'list_item+',
         group: 'block',
         attrs: {
-            bulletStyle: { default: "" },
+            bulletStyle: { default: 0 },
             mapStyle: { default: "decimal" }
         },
         toDOM(node: Node<any>) {
             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" : "";
+            const decMap = bs === 1 ? "decimal" : bs === 2 ? "decimal2" : bs === 3 ? "decimal3" : bs === 4 ? "decimal4" : "";
+            const multiMap = bs === 1 ? "decimal" : bs === 2 ? "upper-alpha" : bs === 3 ? "lower-roman" : bs === 4 ? "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];
diff --git a/src/client/util/TooltipLinkingMenu.tsx b/src/client/util/TooltipLinkingMenu.tsx
index 55e0eb909..e6d6c471f 100644
--- a/src/client/util/TooltipLinkingMenu.tsx
+++ b/src/client/util/TooltipLinkingMenu.tsx
@@ -1,23 +1,9 @@
-import { action, IReactionDisposer, reaction } from "mobx";
-import { Dropdown, DropdownSubmenu, MenuItem, MenuItemSpec, renderGrouped, icons, } from "prosemirror-menu"; //no import css
-import { baseKeymap, lift } from "prosemirror-commands";
-import { history, redo, undo } from "prosemirror-history";
-import { keymap } from "prosemirror-keymap";
-import { EditorState, Transaction, NodeSelection, TextSelection } from "prosemirror-state";
+import { EditorState } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
-import { schema } from "./RichTextSchema";
-import { Schema, NodeType, MarkType } from "prosemirror-model";
-import React = require("react");
+import { FieldViewProps } from "../views/nodes/FieldView";
 import "./TooltipTextMenu.scss";
+import React = require("react");
 const { toggleMark, setBlockType, wrapIn } = require("prosemirror-commands");
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { wrapInList, bulletList, liftListItem, listItem } from 'prosemirror-schema-list';
-import {
-    faListUl,
-} from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { FieldViewProps } from "../views/nodes/FieldView";
-import { throwStatement } from "babel-types";
 
 const SVG = "http://www.w3.org/2000/svg";
 
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index e979e6cde..3b4b7f05a 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -3,7 +3,7 @@ import { faListUl } from '@fortawesome/free-solid-svg-icons';
 import { action, observable } from "mobx";
 import { Dropdown, icons, MenuItem } from "prosemirror-menu"; //no import css
 import { Mark, MarkType, Node as ProsNode, NodeType, ResolvedPos, Schema } from "prosemirror-model";
-import { liftListItem, wrapInList } from 'prosemirror-schema-list';
+import { wrapInList } from 'prosemirror-schema-list';
 import { EditorState, NodeSelection, TextSelection } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { Doc, Field, Opt } from "../../new_fields/Doc";
@@ -525,7 +525,7 @@ export class TooltipTextMenu {
                 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.bulletStyle = 1;
                         path[i].attrs.mapStyle = (nodeType as any).attrs.mapStyle;
                         break;
                     }
diff --git a/src/client/util/prosemirrorPatches.js b/src/client/util/prosemirrorPatches.js
new file mode 100644
index 000000000..c273c2323
--- /dev/null
+++ b/src/client/util/prosemirrorPatches.js
@@ -0,0 +1,62 @@
+'use strict';
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+var prosemirrorTransform = require('prosemirror-transform');
+var prosemirrorModel = require('prosemirror-model');
+
+exports.liftListItem = liftListItem;
+// :: (NodeType) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool
+// Create a command to lift the list item around the selection up into
+// a wrapping list.
+function liftListItem(itemType) {
+    return function (tx, dispatch) {
+        var ref = tx.selection;
+        var $from = ref.$from;
+        var $to = ref.$to;
+        var range = $from.blockRange($to, function (node) { return node.childCount && node.firstChild.type == itemType; });
+        if (!range) { return false }
+        if (!dispatch) { return true }
+        if ($from.node(range.depth - 1).type == itemType) // Inside a parent list
+        { return liftToOuterList(tx, dispatch, itemType, range) }
+        else // Outer list node
+        { return liftOutOfList(tx, dispatch, range) }
+    }
+}
+
+function liftToOuterList(tr, dispatch, itemType, range) {
+    var end = range.end, endOfList = range.$to.end(range.depth);
+    if (end < endOfList) {
+        // There are siblings after the lifted items, which must become
+        // children of the last item
+        tr.step(new prosemirrorTransform.ReplaceAroundStep(end - 1, endOfList, end, endOfList,
+            new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(itemType.create(null, range.parent.copy())), 1, 0), 1, true));
+        range = new prosemirrorModel.NodeRange(tr.doc.resolve(range.$from.pos), tr.doc.resolve(endOfList), range.depth);
+    }
+    dispatch(tr.lift(range, prosemirrorTransform.liftTarget(range)).scrollIntoView());
+    return true
+}
+
+function liftOutOfList(tr, dispatch, range) {
+    var list = range.parent;
+    // Merge the list items into a single big item
+    for (var pos = range.end, i = range.endIndex - 1, e = range.startIndex; i > e; i--) {
+        pos -= list.child(i).nodeSize;
+        tr.delete(pos - 1, pos + 1);
+    }
+    var $start = tr.doc.resolve(range.start), item = $start.nodeAfter;
+    var atStart = range.startIndex == 0, atEnd = range.endIndex == list.childCount;
+    var parent = $start.node(-1), indexBefore = $start.index(-1);
+    if (!parent.canReplace(indexBefore + (atStart ? 0 : 1), indexBefore + 1,
+        item.content.append(atEnd ? prosemirrorModel.Fragment.empty : prosemirrorModel.Fragment.from(list)))) { return false }
+    var start = $start.pos, end = start + item.nodeSize;
+    // Strip off the surrounding list. At the sides where we're not at
+    // the end of the list, the existing list is closed. At sides where
+    // this is the end, it is overwritten to its end.
+    tr.step(new prosemirrorTransform.ReplaceAroundStep(start - (atStart ? 1 : 0), end + (atEnd ? 1 : 0), start + 1, end - 1,
+        new prosemirrorModel.Slice((atStart ? prosemirrorModel.Fragment.empty : prosemirrorModel.Fragment.from(list.copy(prosemirrorModel.Fragment.empty)))
+            .append(atEnd ? prosemirrorModel.Fragment.empty : prosemirrorModel.Fragment.from(list.copy(prosemirrorModel.Fragment.empty))),
+            atStart ? 0 : 1, atEnd ? 0 : 1), atStart ? 0 : 1));
+    dispatch(tr.scrollIntoView());
+    return true
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 4a1d94325d5d1b5641cd280e89c442c114074e8d Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 3 Sep 2019 08:03:43 -0400
Subject: cleanup names for formattedTextBoxComment stuff.  fixed brushing bug
 with user_mark.

---
 src/client/util/RichTextSchema.tsx                 |  2 +-
 src/client/util/TooltipTextMenu.tsx                |  6 +-
 src/client/views/nodes/FormattedTextBox.tsx        | 12 ++--
 src/client/views/nodes/FormattedTextBoxComment.tsx | 70 +++++++++++-----------
 4 files changed, 41 insertions(+), 49 deletions(-)

(limited to 'src/client/util/TooltipTextMenu.tsx')

diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 3161467b8..7911cf629 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -346,7 +346,7 @@ export const marks: { [index: string]: MarkSpec } = {
             return hidden ?
                 (node.attrs.opened ?
                     ['span', { class: "userMarkOpen" }, 0] :
-                    ['span', { class: "userMark" }, ['span', { style: "font-size:2" }, 0]]
+                    ['span', { class: "userMark" }, ['span', 0]]
                 ) :
                 ['span', 0];
         }
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 3b4b7f05a..ce7b04e31 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -60,8 +60,6 @@ export class TooltipTextMenu {
     @observable
     private _storedMarks: Mark<any>[] | null | undefined;
 
-    public HackToFixTextSelectionGlitch: boolean = false;
-
 
     constructor(view: EditorView, editorProps: FieldViewProps & FormattedTextBoxProps) {
         this.view = view;
@@ -629,7 +627,7 @@ export class TooltipTextMenu {
                 if (!this.view.state.selection.empty && $from && $from.nodeAfter) {
                     if (this._brushMarks && to - from > 0) {
                         this.view.dispatch(this.view.state.tr.removeMark(from, to));
-                        this._brushMarks.forEach((mark: Mark) => {
+                        Array.from(this._brushMarks).filter(m => m.type !== schema.marks.user_mark).forEach((mark: Mark) => {
                             const markType = mark.type;
                             this.changeToMarkInGroup(markType, this.view, []);
 
@@ -876,8 +874,6 @@ export class TooltipTextMenu {
                 this.updateFontSizeDropdown("Various");
             }
         }
-        !this.HackToFixTextSelectionGlitch &&
-            this.view.dispatch(this.view.state.tr.setStoredMarks(this._activeMarks)); // bcz: what's the purpose of this line?  It messes up text selection without the Hack.
 
         this.update_mark_doms();
     }
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 93ac2f06f..6232dd3ab 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -37,8 +37,7 @@ import { DocumentDecorations } from '../DocumentDecorations';
 import { DictationManager } from '../../util/DictationManager';
 import { ReplaceStep } from 'prosemirror-transform';
 import { DocumentType } from '../../documents/DocumentTypes';
-import { selectionSizePlugin, findStartOfMark, findUserMark, findEndOfMark, findOtherUserMark, SelectionSizeTooltip } from './FormattedTextBoxComment';
-import { date } from 'serializr';
+import { formattedTextBoxCommentPlugin, FormattedTextBoxComment } from './FormattedTextBoxComment';
 
 library.add(faEdit);
 library.add(faSmile, faTextHeight, faUpload);
@@ -172,9 +171,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     dispatchTransaction = (tx: Transaction) => {
         if (this._editorView) {
             const state = this._editorView.state.apply(tx);
-            FormattedTextBox._toolTipTextMenu && (FormattedTextBox._toolTipTextMenu.HackToFixTextSelectionGlitch = true);
             this._editorView.updateState(state);
-            FormattedTextBox._toolTipTextMenu && (FormattedTextBox._toolTipTextMenu.HackToFixTextSelectionGlitch = false);
             if (state.selection.empty && FormattedTextBox._toolTipTextMenu && tx.storedMarks) {
                 FormattedTextBox._toolTipTextMenu.mark_key_pressed(tx.storedMarks);
             }
@@ -327,7 +324,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                         attributes: { class: "ProseMirror-example-setup-style" }
                     }
                 }),
-                selectionSizePlugin
+                formattedTextBoxCommentPlugin
             ] : [
                     history(),
                     keymap(buildKeymap(schema)),
@@ -713,7 +710,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     }
 
     onPointerUp = (e: React.PointerEvent): void => {
-        SelectionSizeTooltip.textBox = this;
+        FormattedTextBoxComment.textBox = this;
         if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
             e.stopPropagation();
         }
@@ -805,8 +802,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             }
 
             if (m < 10) m = '0' + m;
-            if (s < 10) s = '0' + s;
-            return now.toLocaleDateString() + ' ' + h + ':' + m + ':' + s + ' ' + ampm;
+            return now.toLocaleDateString() + ' ' + h + ':' + m + ' ' + ampm;
         }
         var markerss = this._editorView!.state.storedMarks || (this._editorView!.state.selection.$to.parentOffset && this._editorView!.state.selection.$from.marks());
         let newMarks = [...(markerss ? markerss.filter(m => m.type !== schema.marks.user_mark) : []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: timenow() })];
diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx
index c368a3f34..255000936 100644
--- a/src/client/views/nodes/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/FormattedTextBoxComment.tsx
@@ -8,8 +8,8 @@ import { DocServer } from "../../DocServer";
 import { Utils } from "../../../Utils";
 import { StrCast } from "../../../new_fields/Types";
 
-export let selectionSizePlugin = new Plugin({
-    view(editorView) { return new SelectionSizeTooltip(editorView); }
+export let formattedTextBoxCommentPlugin = new Plugin({
+    view(editorView) { return new FormattedTextBoxComment(editorView); }
 });
 export function findOtherUserMark(marks: Mark[]): Mark | undefined {
     return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail);
@@ -42,7 +42,7 @@ export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (mark
 }
 
 
-export class SelectionSizeTooltip {
+export class FormattedTextBoxComment {
     static tooltip: HTMLElement;
     static tooltipText: HTMLElement;
     static start: number;
@@ -51,39 +51,39 @@ export class SelectionSizeTooltip {
     static opened: boolean;
     static textBox: any;
     constructor(view: any) {
-        if (!SelectionSizeTooltip.tooltip) {
+        if (!FormattedTextBoxComment.tooltip) {
             const root = document.getElementById("root");
             let input = document.createElement("input");
             input.type = "checkbox";
-            SelectionSizeTooltip.tooltip = document.createElement("div");
-            SelectionSizeTooltip.tooltipText = document.createElement("div");
-            SelectionSizeTooltip.tooltip.appendChild(SelectionSizeTooltip.tooltipText);
-            SelectionSizeTooltip.tooltip.className = "FormattedTextBox-tooltip";
-            SelectionSizeTooltip.tooltip.style.pointerEvents = "all";
-            SelectionSizeTooltip.tooltip.appendChild(input);
-            SelectionSizeTooltip.tooltip.onpointerdown = (e: PointerEvent) => {
+            FormattedTextBoxComment.tooltip = document.createElement("div");
+            FormattedTextBoxComment.tooltipText = document.createElement("div");
+            FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText);
+            FormattedTextBoxComment.tooltip.className = "FormattedTextBox-tooltip";
+            FormattedTextBoxComment.tooltip.style.pointerEvents = "all";
+            FormattedTextBoxComment.tooltip.appendChild(input);
+            FormattedTextBoxComment.tooltip.onpointerdown = (e: PointerEvent) => {
                 let keep = e.target && (e.target as any).type === "checkbox";
-                SelectionSizeTooltip.opened = keep || !SelectionSizeTooltip.opened;
-                SelectionSizeTooltip.textBox && SelectionSizeTooltip.textBox.setAnnotation(
-                    SelectionSizeTooltip.start, SelectionSizeTooltip.end, SelectionSizeTooltip.mark,
-                    SelectionSizeTooltip.opened, keep);
+                FormattedTextBoxComment.opened = keep || !FormattedTextBoxComment.opened;
+                FormattedTextBoxComment.textBox && FormattedTextBoxComment.textBox.setAnnotation(
+                    FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark,
+                    FormattedTextBoxComment.opened, keep);
             };
-            root && root.appendChild(SelectionSizeTooltip.tooltip);
+            root && root.appendChild(FormattedTextBoxComment.tooltip);
         }
         this.update(view, undefined);
     }
 
     public static Hide() {
-        SelectionSizeTooltip.textBox = undefined;
-        SelectionSizeTooltip.tooltip && (SelectionSizeTooltip.tooltip.style.display = "none");
+        FormattedTextBoxComment.textBox = undefined;
+        FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none");
     }
     public static SetState(textBox: any, opened: boolean, start: number, end: number, mark: Mark) {
-        SelectionSizeTooltip.textBox = textBox;
-        SelectionSizeTooltip.start = start;
-        SelectionSizeTooltip.end = end;
-        SelectionSizeTooltip.mark = mark;
-        SelectionSizeTooltip.opened = opened;
-        SelectionSizeTooltip.tooltip && (SelectionSizeTooltip.tooltip.style.display = "");
+        FormattedTextBoxComment.textBox = textBox;
+        FormattedTextBoxComment.start = start;
+        FormattedTextBoxComment.end = end;
+        FormattedTextBoxComment.mark = mark;
+        FormattedTextBoxComment.opened = opened;
+        FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "");
     }
 
     update(view: EditorView, lastState?: EditorState) {
@@ -102,10 +102,10 @@ export class SelectionSizeTooltip {
             let mark = child && findOtherUserMark(child.marks);
             let noselection = view.state.selection.$from === view.state.selection.$to;
             if (mark && child && (nbef || naft) && (!mark.attrs.opened || noselection)) {
-                SelectionSizeTooltip.SetState(this, mark.attrs.opened, spos, epos, mark);
+                FormattedTextBoxComment.SetState(this, mark.attrs.opened, spos, epos, mark);
             }
             if (mark && child && nbef && naft) {
-                SelectionSizeTooltip.tooltipText.textContent = mark.attrs.userid + " " + mark.attrs.modified;
+                FormattedTextBoxComment.tooltipText.textContent = mark.attrs.userid + " " + mark.attrs.modified;
                 // These are in screen coordinates
                 // let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to);
                 let start = view.coordsAtPos(state.selection.from - nbef), end = view.coordsAtPos(state.selection.from - nbef);
@@ -114,23 +114,23 @@ export class SelectionSizeTooltip {
                 // Find a center-ish x position from the selection endpoints (when
                 // crossing lines, end may be more to the left)
                 let left = Math.max((start.left + end.left) / 2, start.left + 3);
-                SelectionSizeTooltip.tooltip.style.left = (left - box.left) + "px";
-                SelectionSizeTooltip.tooltip.style.bottom = (box.bottom - start.top) + "px";
+                FormattedTextBoxComment.tooltip.style.left = (left - box.left) + "px";
+                FormattedTextBoxComment.tooltip.style.bottom = (box.bottom - start.top) + "px";
                 set = "";
             }
         }
         if (set === "none" && state.selection.$from) {
-            SelectionSizeTooltip.textBox = undefined;
+            FormattedTextBoxComment.textBox = undefined;
             let nbef = findStartOfMark(state.selection.$from, view, findLinkMark);
             let naft = findEndOfMark(state.selection.$from, view, findLinkMark);
             let child = state.selection.$from.nodeBefore;
             let mark = child && findLinkMark(child.marks);
             if (mark && child && nbef && naft) {
-                SelectionSizeTooltip.tooltipText.textContent = "link : " + (mark.attrs.title || mark.attrs.href);
+                FormattedTextBoxComment.tooltipText.textContent = "link : " + (mark.attrs.title || mark.attrs.href);
                 if (mark.attrs.href.indexOf(Utils.prepend("/doc/")) === 0) {
                     let docTarget = mark.attrs.href.replace(Utils.prepend("/doc/"), "").split("?")[0];
                     docTarget && DocServer.GetRefField(docTarget).then(linkDoc =>
-                        (linkDoc as Doc) && (SelectionSizeTooltip.tooltipText.textContent = "link :" + StrCast((linkDoc as Doc)!.title)));
+                        (linkDoc as Doc) && (FormattedTextBoxComment.tooltipText.textContent = "link :" + StrCast((linkDoc as Doc)!.title)));
                 }
                 // These are in screen coordinates
                 // let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to);
@@ -140,13 +140,13 @@ export class SelectionSizeTooltip {
                 // Find a center-ish x position from the selection endpoints (when
                 // crossing lines, end may be more to the left)
                 let left = Math.max((start.left + end.left) / 2, start.left + 3);
-                SelectionSizeTooltip.tooltip.style.left = (left - box.left) + "px";
-                SelectionSizeTooltip.tooltip.style.bottom = (box.bottom - start.top) + "px";
+                FormattedTextBoxComment.tooltip.style.left = (left - box.left) + "px";
+                FormattedTextBoxComment.tooltip.style.bottom = (box.bottom - start.top) + "px";
                 set = "";
             }
         }
-        SelectionSizeTooltip.tooltip && (SelectionSizeTooltip.tooltip.style.display = set);
+        FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = set);
     }
 
-    destroy() { SelectionSizeTooltip.tooltip.style.display = "none"; }
+    destroy() { FormattedTextBoxComment.tooltip.style.display = "none"; }
 }
-- 
cgit v1.2.3-70-g09d2

