@fiduswriter/editor 0.1.41 → 0.1.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/state_plugins/jump_hidden_nodes.d.ts.map +1 -1
- package/dist/state_plugins/jump_hidden_nodes.js +79 -21
- package/dist/state_plugins/jump_hidden_nodes.js.map +1 -1
- package/dist/state_plugins/placeholders.d.ts +2 -2
- package/dist/state_plugins/placeholders.d.ts.map +1 -1
- package/dist/state_plugins/placeholders.js +51 -19
- package/dist/state_plugins/placeholders.js.map +1 -1
- package/package.json +1 -1
- package/src/state_plugins/jump_hidden_nodes.ts +95 -28
- package/src/state_plugins/placeholders.ts +73 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jump_hidden_nodes.d.ts","sourceRoot":"","sources":["../../src/state_plugins/jump_hidden_nodes.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAA2B,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"jump_hidden_nodes.d.ts","sourceRoot":"","sources":["../../src/state_plugins/jump_hidden_nodes.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,MAAM,EAA2B,MAAM,mBAAmB,CAAA;AAoBlE,eAAO,MAAM,qBAAqB,GAAI,UAAU;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC,gBA6I3D,CAAA"}
|
|
@@ -15,6 +15,61 @@ const posHidden = ($pos) => {
|
|
|
15
15
|
const key = new PluginKey("jump-hidden-nodes");
|
|
16
16
|
export const jumpHiddenNodesPlugin = (_options) => new Plugin({
|
|
17
17
|
key,
|
|
18
|
+
props: {
|
|
19
|
+
handleKeyDown: (view, event) => {
|
|
20
|
+
if (event.key !== "ArrowLeft") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const { selection, doc } = view.state;
|
|
24
|
+
if (!selection.empty) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const $pos = selection.$from;
|
|
28
|
+
if ($pos.depth < 2) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
// Intercept ArrowLeft when at the beginning of a textblock
|
|
32
|
+
// OR inside an empty textblock whose preceding doc-level
|
|
33
|
+
// sibling is hidden. This handles the case where clicking
|
|
34
|
+
// an empty body paragraph and pressing LEFT should land in
|
|
35
|
+
// the abstract (skipping hidden parts like keywords).
|
|
36
|
+
const atStart = $pos.parentOffset === 0;
|
|
37
|
+
const isEmptyTextblock = $pos.parent.type.isTextblock &&
|
|
38
|
+
$pos.parent.content.size === 0;
|
|
39
|
+
if (!atStart && !isEmptyTextblock) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
// Find previous sibling of the parent doc-level node
|
|
43
|
+
const { index } = doc.content.findIndex($pos.pos);
|
|
44
|
+
if (index < 1) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
const prevSibling = doc.child(index - 1);
|
|
48
|
+
if (!prevSibling.attrs.hidden) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
// Walk backward to the previous non-hidden position
|
|
52
|
+
const dir = -1;
|
|
53
|
+
let newPos = selection.from, hidden = true, validTextSelection = false, validGapCursor = false;
|
|
54
|
+
let new$pos = selection.$from;
|
|
55
|
+
while (hidden ||
|
|
56
|
+
(!validGapCursor && !validTextSelection)) {
|
|
57
|
+
newPos += dir;
|
|
58
|
+
if (newPos === 0) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
new$pos = doc.resolve(newPos);
|
|
62
|
+
validTextSelection = new$pos.parent.inlineContent;
|
|
63
|
+
validGapCursor = GapCursor.valid(new$pos);
|
|
64
|
+
hidden = posHidden(new$pos);
|
|
65
|
+
}
|
|
66
|
+
const trSelection = validTextSelection
|
|
67
|
+
? new TextSelection(new$pos)
|
|
68
|
+
: new GapCursor(new$pos);
|
|
69
|
+
view.dispatch(view.state.tr.setSelection(trSelection));
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
18
73
|
appendTransaction: (trs, oldState, state) => {
|
|
19
74
|
if (!state.selection.empty) {
|
|
20
75
|
// Only applies to collapsed selection
|
|
@@ -43,33 +98,36 @@ export const jumpHiddenNodesPlugin = (_options) => new Plugin({
|
|
|
43
98
|
}
|
|
44
99
|
// Handle boundary crossing: cursor is at the start of a visible
|
|
45
100
|
// doc-level part whose preceding sibling is hidden. Use
|
|
46
|
-
//
|
|
101
|
+
// findIndex to locate the previous doc child and check if
|
|
102
|
+
// it is hidden.
|
|
47
103
|
if (selectionSet &&
|
|
48
104
|
!posHidden(state.selection.$from) &&
|
|
49
105
|
state.selection.$from.depth >= 2) {
|
|
50
106
|
const $pos = state.selection.$from;
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
107
|
+
const { index } = state.doc.content.findIndex($pos.pos);
|
|
108
|
+
if (index >= 1) {
|
|
109
|
+
const prevSibling = state.doc.child(index - 1);
|
|
110
|
+
if (prevSibling.attrs.hidden) {
|
|
111
|
+
const dir = -1;
|
|
112
|
+
let newPos = state.selection.from, hidden = true, validTextSelection = false, validGapCursor = false;
|
|
113
|
+
let new$pos = state.selection.$from;
|
|
114
|
+
while (hidden ||
|
|
115
|
+
(!validGapCursor && !validTextSelection)) {
|
|
116
|
+
newPos += dir;
|
|
117
|
+
if (newPos === 0) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
new$pos = state.doc.resolve(newPos);
|
|
121
|
+
validTextSelection =
|
|
122
|
+
new$pos.parent.inlineContent;
|
|
123
|
+
validGapCursor = GapCursor.valid(new$pos);
|
|
124
|
+
hidden = posHidden(new$pos);
|
|
63
125
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
126
|
+
const selection = validTextSelection
|
|
127
|
+
? new TextSelection(new$pos)
|
|
128
|
+
: new GapCursor(new$pos);
|
|
129
|
+
return state.tr.setSelection(selection);
|
|
68
130
|
}
|
|
69
|
-
const selection = validTextSelection
|
|
70
|
-
? new TextSelection(new$pos)
|
|
71
|
-
: new GapCursor(new$pos);
|
|
72
|
-
return state.tr.setSelection(selection);
|
|
73
131
|
}
|
|
74
132
|
}
|
|
75
133
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jump_hidden_nodes.js","sourceRoot":"","sources":["../../src/state_plugins/jump_hidden_nodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAA;AAC/C,OAAO,EAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAC,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"jump_hidden_nodes.js","sourceRoot":"","sources":["../../src/state_plugins/jump_hidden_nodes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Plugin } from "prosemirror-state";
|
|
2
2
|
import { DecorationSet } from "prosemirror-view";
|
|
3
|
-
export declare const placeholdersPlugin: (
|
|
3
|
+
export declare const placeholdersPlugin: (options: {
|
|
4
4
|
editor: unknown;
|
|
5
|
-
}) => Plugin<
|
|
5
|
+
}) => Plugin<false | DecorationSet>;
|
|
6
6
|
//# sourceMappingURL=placeholders.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"placeholders.d.ts","sourceRoot":"","sources":["../../src/state_plugins/placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAY,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAa,aAAa,EAAC,MAAM,kBAAkB,CAAA;AAK1D,eAAO,MAAM,kBAAkB,GAAI,
|
|
1
|
+
{"version":3,"file":"placeholders.d.ts","sourceRoot":"","sources":["../../src/state_plugins/placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAY,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAa,aAAa,EAAC,MAAM,kBAAkB,CAAA;AAK1D,eAAO,MAAM,kBAAkB,GAAI,SAAS;IAAC,MAAM,EAAE,OAAO,CAAA;CAAC,kCAqH5D,CAAA"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2
2
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
3
3
|
const key = new PluginKey("placeholders");
|
|
4
|
-
export const placeholdersPlugin = (
|
|
4
|
+
export const placeholdersPlugin = (options) => {
|
|
5
5
|
function calculatePlaceHolderDecorations(state) {
|
|
6
6
|
const anchor = state.selection.$anchor;
|
|
7
7
|
const head = state.selection.$head;
|
|
8
8
|
if (!anchor || !head) {
|
|
9
|
-
return;
|
|
9
|
+
return false;
|
|
10
10
|
}
|
|
11
11
|
const anchorPart = anchor.node(1);
|
|
12
12
|
const headPart = head.node(1);
|
|
13
13
|
if (!anchorPart || !headPart) {
|
|
14
|
-
return;
|
|
14
|
+
return false;
|
|
15
15
|
}
|
|
16
16
|
const currentPart = anchorPart === headPart ? anchorPart : false;
|
|
17
17
|
const decorations = [];
|
|
@@ -22,20 +22,53 @@ export const placeholdersPlugin = (_options) => {
|
|
|
22
22
|
state.schema.nodes["tags_part"],
|
|
23
23
|
state.schema.nodes["contributors_part"]
|
|
24
24
|
].includes(partElement.type) &&
|
|
25
|
-
|
|
25
|
+
options.editor.docInfo.access_rights === "write") {
|
|
26
|
+
// We don't need to render placeholders for these kinds
|
|
27
|
+
// of nodes in write mode as their nodeviews will take
|
|
28
|
+
// care of that.
|
|
26
29
|
return;
|
|
27
30
|
}
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const text = partElement.type === state.schema.nodes["title"]
|
|
32
|
+
? `${gettext("Title")}...`
|
|
33
|
+
: `${partElement.attrs.title}...`;
|
|
34
|
+
const placeHolder = document.createElement("span");
|
|
35
|
+
placeHolder.classList.add("placeholder");
|
|
36
|
+
placeHolder.setAttribute("data-placeholder", text);
|
|
37
|
+
if (currentPart === partElement) {
|
|
38
|
+
placeHolder.classList.add("selected");
|
|
39
|
+
}
|
|
40
|
+
let position = 1 + offset;
|
|
41
|
+
// position of decorator: 2 to get inside (doc (1))
|
|
42
|
+
if (!partElement.isTextblock) {
|
|
43
|
+
// In block nodes that are not text blocks (body + abstract)
|
|
44
|
+
// place inside the first child node (a paragraph).
|
|
45
|
+
position += 1;
|
|
46
|
+
}
|
|
47
|
+
decorations.push(Decoration.widget(position, placeHolder, {
|
|
48
|
+
side: 1
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
else if (["richtext_part", "table_part"].includes(partElement.type.name)) {
|
|
52
|
+
partElement.descendants((node, pos) => {
|
|
53
|
+
if (["figure", "table"].includes(node.type.name) &&
|
|
54
|
+
!node.attrs.caption) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (["figure_caption", "table_caption"].includes(node.type.name) &&
|
|
58
|
+
node.childCount === 0 &&
|
|
59
|
+
state.selection.$anchor.parent !== node) {
|
|
60
|
+
decorations.push(Decoration.node(1 + offset + pos, 1 + offset + pos + node.nodeSize, {
|
|
61
|
+
class: "empty",
|
|
62
|
+
"data-placeholder": `${gettext("Caption")}...`
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
34
66
|
});
|
|
35
|
-
decorations.push(widget);
|
|
36
67
|
}
|
|
37
68
|
});
|
|
38
|
-
return
|
|
69
|
+
return decorations.length
|
|
70
|
+
? DecorationSet.create(state.doc, decorations)
|
|
71
|
+
: false;
|
|
39
72
|
}
|
|
40
73
|
return new Plugin({
|
|
41
74
|
key,
|
|
@@ -43,18 +76,17 @@ export const placeholdersPlugin = (_options) => {
|
|
|
43
76
|
init(_config, state) {
|
|
44
77
|
return calculatePlaceHolderDecorations(state);
|
|
45
78
|
},
|
|
46
|
-
apply(
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
oldState.selection.$head !== newState.selection.$head) {
|
|
50
|
-
return calculatePlaceHolderDecorations(newState);
|
|
79
|
+
apply(tr, _prev, oldState, state) {
|
|
80
|
+
if (tr.docChanged || tr.selectionSet) {
|
|
81
|
+
return calculatePlaceHolderDecorations(state);
|
|
51
82
|
}
|
|
52
|
-
return
|
|
83
|
+
return key.getState(oldState);
|
|
53
84
|
}
|
|
54
85
|
},
|
|
55
86
|
props: {
|
|
56
87
|
decorations(state) {
|
|
57
|
-
|
|
88
|
+
const decorationSet = key.getState(state);
|
|
89
|
+
return decorationSet || null;
|
|
58
90
|
}
|
|
59
91
|
}
|
|
60
92
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../src/state_plugins/placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAC,UAAU,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAA;AAG1D,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,cAAc,CAAC,CAAA;AAEzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../src/state_plugins/placeholders.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {GapCursor} from "prosemirror-gapcursor"
|
|
2
2
|
import {Plugin, PluginKey, TextSelection} from "prosemirror-state"
|
|
3
3
|
import type {ResolvedPos} from "prosemirror-model"
|
|
4
|
+
import type {EditorView} from "prosemirror-view"
|
|
4
5
|
|
|
5
6
|
const posHidden = ($pos: ResolvedPos) => {
|
|
6
7
|
let hidden = false
|
|
@@ -21,6 +22,69 @@ const key = new PluginKey("jump-hidden-nodes")
|
|
|
21
22
|
export const jumpHiddenNodesPlugin = (_options: {editor: unknown}) =>
|
|
22
23
|
new Plugin({
|
|
23
24
|
key,
|
|
25
|
+
props: {
|
|
26
|
+
handleKeyDown: (view: EditorView, event: KeyboardEvent) => {
|
|
27
|
+
if (event.key !== "ArrowLeft") {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
const {selection, doc} = view.state
|
|
31
|
+
if (!selection.empty) {
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
const $pos = selection.$from
|
|
35
|
+
if ($pos.depth < 2) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
// Intercept ArrowLeft when at the beginning of a textblock
|
|
39
|
+
// OR inside an empty textblock whose preceding doc-level
|
|
40
|
+
// sibling is hidden. This handles the case where clicking
|
|
41
|
+
// an empty body paragraph and pressing LEFT should land in
|
|
42
|
+
// the abstract (skipping hidden parts like keywords).
|
|
43
|
+
const atStart = $pos.parentOffset === 0
|
|
44
|
+
const isEmptyTextblock =
|
|
45
|
+
$pos.parent.type.isTextblock &&
|
|
46
|
+
$pos.parent.content.size === 0
|
|
47
|
+
if (!atStart && !isEmptyTextblock) {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
// Find previous sibling of the parent doc-level node
|
|
51
|
+
const {index} = (doc.content as any).findIndex($pos.pos)
|
|
52
|
+
if (index < 1) {
|
|
53
|
+
return false
|
|
54
|
+
}
|
|
55
|
+
const prevSibling = doc.child(index - 1)
|
|
56
|
+
if (!prevSibling.attrs.hidden) {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
// Walk backward to the previous non-hidden position
|
|
60
|
+
const dir = -1
|
|
61
|
+
let newPos = selection.from,
|
|
62
|
+
hidden = true,
|
|
63
|
+
validTextSelection = false,
|
|
64
|
+
validGapCursor = false
|
|
65
|
+
let new$pos: ResolvedPos = selection.$from
|
|
66
|
+
while (
|
|
67
|
+
hidden ||
|
|
68
|
+
(!validGapCursor && !validTextSelection)
|
|
69
|
+
) {
|
|
70
|
+
newPos += dir
|
|
71
|
+
if (newPos === 0) {
|
|
72
|
+
return false
|
|
73
|
+
}
|
|
74
|
+
new$pos = doc.resolve(newPos)
|
|
75
|
+
validTextSelection = new$pos.parent.inlineContent
|
|
76
|
+
validGapCursor = (GapCursor as any).valid(new$pos)
|
|
77
|
+
hidden = posHidden(new$pos)
|
|
78
|
+
}
|
|
79
|
+
const trSelection = validTextSelection
|
|
80
|
+
? new TextSelection(new$pos)
|
|
81
|
+
: new GapCursor(new$pos)
|
|
82
|
+
view.dispatch(
|
|
83
|
+
view.state.tr.setSelection(trSelection)
|
|
84
|
+
)
|
|
85
|
+
return true
|
|
86
|
+
}
|
|
87
|
+
},
|
|
24
88
|
appendTransaction: (trs, oldState, state) => {
|
|
25
89
|
if (!state.selection.empty) {
|
|
26
90
|
// Only applies to collapsed selection
|
|
@@ -53,42 +117,45 @@ export const jumpHiddenNodesPlugin = (_options: {editor: unknown}) =>
|
|
|
53
117
|
}
|
|
54
118
|
// Handle boundary crossing: cursor is at the start of a visible
|
|
55
119
|
// doc-level part whose preceding sibling is hidden. Use
|
|
56
|
-
//
|
|
120
|
+
// findIndex to locate the previous doc child and check if
|
|
121
|
+
// it is hidden.
|
|
57
122
|
if (
|
|
58
123
|
selectionSet &&
|
|
59
124
|
!posHidden(state.selection.$from) &&
|
|
60
125
|
state.selection.$from.depth >= 2
|
|
61
126
|
) {
|
|
62
127
|
const $pos = state.selection.$from
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
128
|
+
const {index} = (state.doc.content as any).findIndex($pos.pos)
|
|
129
|
+
if (index >= 1) {
|
|
130
|
+
const prevSibling = state.doc.child(index - 1)
|
|
131
|
+
if (prevSibling.attrs.hidden) {
|
|
132
|
+
const dir = -1
|
|
133
|
+
let newPos = state.selection.from,
|
|
134
|
+
hidden = true,
|
|
135
|
+
validTextSelection = false,
|
|
136
|
+
validGapCursor = false
|
|
137
|
+
let new$pos: ResolvedPos = state.selection.$from
|
|
138
|
+
while (
|
|
139
|
+
hidden ||
|
|
140
|
+
(!validGapCursor && !validTextSelection)
|
|
141
|
+
) {
|
|
142
|
+
newPos += dir
|
|
143
|
+
if (newPos === 0) {
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
new$pos = state.doc.resolve(newPos)
|
|
147
|
+
validTextSelection =
|
|
148
|
+
new$pos.parent.inlineContent
|
|
149
|
+
validGapCursor = (GapCursor as any).valid(
|
|
150
|
+
new$pos
|
|
151
|
+
)
|
|
152
|
+
hidden = posHidden(new$pos)
|
|
82
153
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
154
|
+
const selection = validTextSelection
|
|
155
|
+
? new TextSelection(new$pos)
|
|
156
|
+
: new GapCursor(new$pos)
|
|
157
|
+
return state.tr.setSelection(selection)
|
|
87
158
|
}
|
|
88
|
-
const selection = validTextSelection
|
|
89
|
-
? new TextSelection(new$pos)
|
|
90
|
-
: new GapCursor(new$pos)
|
|
91
|
-
return state.tr.setSelection(selection)
|
|
92
159
|
}
|
|
93
160
|
}
|
|
94
161
|
return undefined
|
|
@@ -4,21 +4,21 @@ import type {EditorState} from "prosemirror-state"
|
|
|
4
4
|
|
|
5
5
|
const key = new PluginKey("placeholders")
|
|
6
6
|
|
|
7
|
-
export const placeholdersPlugin = (
|
|
8
|
-
function calculatePlaceHolderDecorations(state: EditorState) {
|
|
7
|
+
export const placeholdersPlugin = (options: {editor: unknown}) => {
|
|
8
|
+
function calculatePlaceHolderDecorations(state: EditorState): DecorationSet | false {
|
|
9
9
|
const anchor = state.selection.$anchor
|
|
10
10
|
const head = state.selection.$head
|
|
11
11
|
if (!anchor || !head) {
|
|
12
|
-
return
|
|
12
|
+
return false
|
|
13
13
|
}
|
|
14
14
|
const anchorPart = anchor.node(1)
|
|
15
15
|
const headPart = head.node(1)
|
|
16
16
|
if (!anchorPart || !headPart) {
|
|
17
|
-
return
|
|
17
|
+
return false
|
|
18
18
|
}
|
|
19
19
|
const currentPart = anchorPart === headPart ? anchorPart : false
|
|
20
20
|
|
|
21
|
-
const decorations:
|
|
21
|
+
const decorations: (ReturnType<typeof Decoration.widget> | ReturnType<typeof Decoration.node>)[] = []
|
|
22
22
|
|
|
23
23
|
state.doc.forEach((partElement, offset) => {
|
|
24
24
|
if (
|
|
@@ -30,26 +30,72 @@ export const placeholdersPlugin = (_options: {editor: unknown}) => {
|
|
|
30
30
|
state.schema.nodes["tags_part"],
|
|
31
31
|
state.schema.nodes["contributors_part"]
|
|
32
32
|
].includes(partElement.type) &&
|
|
33
|
-
|
|
33
|
+
(options.editor as any).docInfo.access_rights === "write"
|
|
34
34
|
) {
|
|
35
|
+
// We don't need to render placeholders for these kinds
|
|
36
|
+
// of nodes in write mode as their nodeviews will take
|
|
37
|
+
// care of that.
|
|
35
38
|
return
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
const text =
|
|
42
|
+
partElement.type === state.schema.nodes["title"]
|
|
43
|
+
? `${gettext("Title")}...`
|
|
44
|
+
: `${partElement.attrs.title}...`
|
|
45
|
+
const placeHolder = document.createElement("span")
|
|
46
|
+
placeHolder.classList.add("placeholder")
|
|
47
|
+
placeHolder.setAttribute("data-placeholder", text)
|
|
48
|
+
if (currentPart === partElement) {
|
|
49
|
+
placeHolder.classList.add("selected")
|
|
50
|
+
}
|
|
51
|
+
let position = 1 + offset
|
|
52
|
+
// position of decorator: 2 to get inside (doc (1))
|
|
53
|
+
if (!partElement.isTextblock) {
|
|
54
|
+
// In block nodes that are not text blocks (body + abstract)
|
|
55
|
+
// place inside the first child node (a paragraph).
|
|
56
|
+
position += 1
|
|
57
|
+
}
|
|
58
|
+
decorations.push(
|
|
59
|
+
Decoration.widget(position, placeHolder, {
|
|
60
|
+
side: 1
|
|
61
|
+
})
|
|
48
62
|
)
|
|
49
|
-
|
|
63
|
+
} else if (
|
|
64
|
+
["richtext_part", "table_part"].includes(partElement.type.name)
|
|
65
|
+
) {
|
|
66
|
+
partElement.descendants((node: any, pos: number) => {
|
|
67
|
+
if (
|
|
68
|
+
["figure", "table"].includes(node.type.name) &&
|
|
69
|
+
!node.attrs.caption
|
|
70
|
+
) {
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
if (
|
|
74
|
+
["figure_caption", "table_caption"].includes(
|
|
75
|
+
node.type.name
|
|
76
|
+
) &&
|
|
77
|
+
node.childCount === 0 &&
|
|
78
|
+
state.selection.$anchor.parent !== node
|
|
79
|
+
) {
|
|
80
|
+
decorations.push(
|
|
81
|
+
Decoration.node(
|
|
82
|
+
1 + offset + pos,
|
|
83
|
+
1 + offset + pos + node.nodeSize,
|
|
84
|
+
{
|
|
85
|
+
class: "empty",
|
|
86
|
+
"data-placeholder": `${gettext("Caption")}...`
|
|
87
|
+
}
|
|
88
|
+
) as any
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
return false
|
|
92
|
+
})
|
|
50
93
|
}
|
|
51
94
|
})
|
|
52
|
-
|
|
95
|
+
|
|
96
|
+
return decorations.length
|
|
97
|
+
? DecorationSet.create(state.doc, decorations)
|
|
98
|
+
: false
|
|
53
99
|
}
|
|
54
100
|
|
|
55
101
|
return new Plugin({
|
|
@@ -58,20 +104,20 @@ export const placeholdersPlugin = (_options: {editor: unknown}) => {
|
|
|
58
104
|
init(_config, state) {
|
|
59
105
|
return calculatePlaceHolderDecorations(state)
|
|
60
106
|
},
|
|
61
|
-
apply(
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
oldState.selection.$anchor !== newState.selection.$anchor ||
|
|
65
|
-
oldState.selection.$head !== newState.selection.$head
|
|
66
|
-
) {
|
|
67
|
-
return calculatePlaceHolderDecorations(newState)
|
|
107
|
+
apply(tr, _prev, oldState, state) {
|
|
108
|
+
if (tr.docChanged || tr.selectionSet) {
|
|
109
|
+
return calculatePlaceHolderDecorations(state)
|
|
68
110
|
}
|
|
69
|
-
return
|
|
111
|
+
return key.getState(oldState)
|
|
70
112
|
}
|
|
71
113
|
},
|
|
72
114
|
props: {
|
|
73
115
|
decorations(state) {
|
|
74
|
-
|
|
116
|
+
const decorationSet = key.getState(state) as
|
|
117
|
+
| DecorationSet
|
|
118
|
+
| false
|
|
119
|
+
| undefined
|
|
120
|
+
return decorationSet || null
|
|
75
121
|
}
|
|
76
122
|
}
|
|
77
123
|
})
|