@atlaskit/editor-plugin-text-formatting 0.1.0
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/.eslintrc.js +7 -0
- package/CHANGELOG.md +1 -0
- package/LICENSE.md +13 -0
- package/README.md +9 -0
- package/dist/cjs/actions.js +188 -0
- package/dist/cjs/commands/clear-formatting.js +111 -0
- package/dist/cjs/commands/text-formatting.js +143 -0
- package/dist/cjs/commands/transform-to-code.js +68 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/plugin.js +133 -0
- package/dist/cjs/pm-plugins/clear-formatting-keymap.js +21 -0
- package/dist/cjs/pm-plugins/clear-formatting.js +36 -0
- package/dist/cjs/pm-plugins/cursor.js +55 -0
- package/dist/cjs/pm-plugins/input-rule.js +274 -0
- package/dist/cjs/pm-plugins/keymap.js +52 -0
- package/dist/cjs/pm-plugins/main.js +113 -0
- package/dist/cjs/pm-plugins/plugin-key.js +9 -0
- package/dist/cjs/pm-plugins/smart-input-rule.js +176 -0
- package/dist/cjs/ui/Toolbar/constants.js +19 -0
- package/dist/cjs/ui/Toolbar/dropdown-menu.js +86 -0
- package/dist/cjs/ui/Toolbar/hooks/clear-formatting-icon.js +55 -0
- package/dist/cjs/ui/Toolbar/hooks/formatting-icons.js +227 -0
- package/dist/cjs/ui/Toolbar/hooks/menu-state.js +23 -0
- package/dist/cjs/ui/Toolbar/hooks/responsive-toolbar-buttons.js +60 -0
- package/dist/cjs/ui/Toolbar/index.js +183 -0
- package/dist/cjs/ui/Toolbar/more-button.js +42 -0
- package/dist/cjs/ui/Toolbar/single-toolbar-buttons.js +49 -0
- package/dist/cjs/ui/Toolbar/types.js +17 -0
- package/dist/cjs/utils/cell-selection.js +12 -0
- package/dist/cjs/utils.js +86 -0
- package/dist/cjs/version.json +5 -0
- package/dist/es2019/actions.js +161 -0
- package/dist/es2019/commands/clear-formatting.js +105 -0
- package/dist/es2019/commands/text-formatting.js +144 -0
- package/dist/es2019/commands/transform-to-code.js +71 -0
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/plugin.js +124 -0
- package/dist/es2019/pm-plugins/clear-formatting-keymap.js +10 -0
- package/dist/es2019/pm-plugins/clear-formatting.js +26 -0
- package/dist/es2019/pm-plugins/cursor.js +52 -0
- package/dist/es2019/pm-plugins/input-rule.js +242 -0
- package/dist/es2019/pm-plugins/keymap.js +43 -0
- package/dist/es2019/pm-plugins/main.js +110 -0
- package/dist/es2019/pm-plugins/plugin-key.js +2 -0
- package/dist/es2019/pm-plugins/smart-input-rule.js +155 -0
- package/dist/es2019/ui/Toolbar/constants.js +20 -0
- package/dist/es2019/ui/Toolbar/dropdown-menu.js +66 -0
- package/dist/es2019/ui/Toolbar/hooks/clear-formatting-icon.js +44 -0
- package/dist/es2019/ui/Toolbar/hooks/formatting-icons.js +212 -0
- package/dist/es2019/ui/Toolbar/hooks/menu-state.js +11 -0
- package/dist/es2019/ui/Toolbar/hooks/responsive-toolbar-buttons.js +48 -0
- package/dist/es2019/ui/Toolbar/index.js +168 -0
- package/dist/es2019/ui/Toolbar/more-button.js +34 -0
- package/dist/es2019/ui/Toolbar/single-toolbar-buttons.js +39 -0
- package/dist/es2019/ui/Toolbar/types.js +10 -0
- package/dist/es2019/utils/cell-selection.js +5 -0
- package/dist/es2019/utils.js +74 -0
- package/dist/es2019/version.json +5 -0
- package/dist/esm/actions.js +168 -0
- package/dist/esm/commands/clear-formatting.js +101 -0
- package/dist/esm/commands/text-formatting.js +134 -0
- package/dist/esm/commands/transform-to-code.js +61 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugin.js +125 -0
- package/dist/esm/pm-plugins/clear-formatting-keymap.js +10 -0
- package/dist/esm/pm-plugins/clear-formatting.js +28 -0
- package/dist/esm/pm-plugins/cursor.js +48 -0
- package/dist/esm/pm-plugins/input-rule.js +257 -0
- package/dist/esm/pm-plugins/keymap.js +43 -0
- package/dist/esm/pm-plugins/main.js +99 -0
- package/dist/esm/pm-plugins/plugin-key.js +2 -0
- package/dist/esm/pm-plugins/smart-input-rule.js +169 -0
- package/dist/esm/ui/Toolbar/constants.js +8 -0
- package/dist/esm/ui/Toolbar/dropdown-menu.js +75 -0
- package/dist/esm/ui/Toolbar/hooks/clear-formatting-icon.js +47 -0
- package/dist/esm/ui/Toolbar/hooks/formatting-icons.js +215 -0
- package/dist/esm/ui/Toolbar/hooks/menu-state.js +15 -0
- package/dist/esm/ui/Toolbar/hooks/responsive-toolbar-buttons.js +50 -0
- package/dist/esm/ui/Toolbar/index.js +174 -0
- package/dist/esm/ui/Toolbar/more-button.js +33 -0
- package/dist/esm/ui/Toolbar/single-toolbar-buttons.js +38 -0
- package/dist/esm/ui/Toolbar/types.js +10 -0
- package/dist/esm/utils/cell-selection.js +5 -0
- package/dist/esm/utils.js +75 -0
- package/dist/esm/version.json +5 -0
- package/dist/types/actions.d.ts +22 -0
- package/dist/types/commands/clear-formatting.d.ts +6 -0
- package/dist/types/commands/text-formatting.d.ts +5 -0
- package/dist/types/commands/transform-to-code.d.ts +2 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/plugin.d.ts +17 -0
- package/dist/types/pm-plugins/clear-formatting-keymap.d.ts +4 -0
- package/dist/types/pm-plugins/clear-formatting.d.ts +8 -0
- package/dist/types/pm-plugins/cursor.d.ts +3 -0
- package/dist/types/pm-plugins/input-rule.d.ts +23 -0
- package/dist/types/pm-plugins/keymap.d.ts +4 -0
- package/dist/types/pm-plugins/main.d.ts +7 -0
- package/dist/types/pm-plugins/plugin-key.d.ts +3 -0
- package/dist/types/pm-plugins/smart-input-rule.d.ts +3 -0
- package/dist/types/ui/Toolbar/constants.d.ts +6 -0
- package/dist/types/ui/Toolbar/dropdown-menu.d.ts +15 -0
- package/dist/types/ui/Toolbar/hooks/clear-formatting-icon.d.ts +7 -0
- package/dist/types/ui/Toolbar/hooks/formatting-icons.d.ts +14 -0
- package/dist/types/ui/Toolbar/hooks/menu-state.d.ts +1 -0
- package/dist/types/ui/Toolbar/hooks/responsive-toolbar-buttons.d.ts +20 -0
- package/dist/types/ui/Toolbar/index.d.ts +25 -0
- package/dist/types/ui/Toolbar/more-button.d.ts +14 -0
- package/dist/types/ui/Toolbar/single-toolbar-buttons.d.ts +10 -0
- package/dist/types/ui/Toolbar/types.d.ts +32 -0
- package/dist/types/utils/cell-selection.d.ts +3 -0
- package/dist/types/utils.d.ts +11 -0
- package/dist/types-ts4.5/actions.d.ts +22 -0
- package/dist/types-ts4.5/commands/clear-formatting.d.ts +6 -0
- package/dist/types-ts4.5/commands/text-formatting.d.ts +5 -0
- package/dist/types-ts4.5/commands/transform-to-code.d.ts +2 -0
- package/dist/types-ts4.5/index.d.ts +3 -0
- package/dist/types-ts4.5/plugin.d.ts +19 -0
- package/dist/types-ts4.5/pm-plugins/clear-formatting-keymap.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/clear-formatting.d.ts +8 -0
- package/dist/types-ts4.5/pm-plugins/cursor.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/input-rule.d.ts +23 -0
- package/dist/types-ts4.5/pm-plugins/keymap.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +7 -0
- package/dist/types-ts4.5/pm-plugins/plugin-key.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/smart-input-rule.d.ts +3 -0
- package/dist/types-ts4.5/ui/Toolbar/constants.d.ts +6 -0
- package/dist/types-ts4.5/ui/Toolbar/dropdown-menu.d.ts +15 -0
- package/dist/types-ts4.5/ui/Toolbar/hooks/clear-formatting-icon.d.ts +7 -0
- package/dist/types-ts4.5/ui/Toolbar/hooks/formatting-icons.d.ts +14 -0
- package/dist/types-ts4.5/ui/Toolbar/hooks/menu-state.d.ts +5 -0
- package/dist/types-ts4.5/ui/Toolbar/hooks/responsive-toolbar-buttons.d.ts +20 -0
- package/dist/types-ts4.5/ui/Toolbar/index.d.ts +25 -0
- package/dist/types-ts4.5/ui/Toolbar/more-button.d.ts +14 -0
- package/dist/types-ts4.5/ui/Toolbar/single-toolbar-buttons.d.ts +10 -0
- package/dist/types-ts4.5/ui/Toolbar/types.d.ts +32 -0
- package/dist/types-ts4.5/utils/cell-selection.d.ts +3 -0
- package/dist/types-ts4.5/utils.d.ts +11 -0
- package/package.json +93 -0
- package/report.api.md +66 -0
- package/tmp/api-report-tmp.d.ts +39 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.markActive = exports.isArrayContainsContent = exports.hasCode = exports.compareItemsArrays = exports.checkFormattingIsPresent = void 0;
|
|
7
|
+
var _mark = require("@atlaskit/editor-common/mark");
|
|
8
|
+
var _clearFormatting = require("./commands/clear-formatting");
|
|
9
|
+
var hasCode = function hasCode(state, pos) {
|
|
10
|
+
var code = state.schema.marks.code;
|
|
11
|
+
var node = pos >= 0 && state.doc.nodeAt(pos);
|
|
12
|
+
if (node) {
|
|
13
|
+
return !!node.marks.filter(function (mark) {
|
|
14
|
+
return mark.type === code;
|
|
15
|
+
}).length;
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Determine if a mark (with specific attribute values) exists anywhere in the selection.
|
|
22
|
+
*/
|
|
23
|
+
exports.hasCode = hasCode;
|
|
24
|
+
var markActive = function markActive(state, mark) {
|
|
25
|
+
var _state$selection = state.selection,
|
|
26
|
+
from = _state$selection.from,
|
|
27
|
+
to = _state$selection.to,
|
|
28
|
+
empty = _state$selection.empty;
|
|
29
|
+
// When the selection is empty, only the active marks apply.
|
|
30
|
+
if (empty) {
|
|
31
|
+
return !!mark.isInSet(state.tr.storedMarks || state.selection.$from.marks());
|
|
32
|
+
}
|
|
33
|
+
// For a non-collapsed selection, the marks on the nodes matter.
|
|
34
|
+
var found = false;
|
|
35
|
+
state.doc.nodesBetween(from, to, function (node) {
|
|
36
|
+
found = found || mark.isInSet(node.marks);
|
|
37
|
+
});
|
|
38
|
+
return found;
|
|
39
|
+
};
|
|
40
|
+
exports.markActive = markActive;
|
|
41
|
+
var blockStylingIsPresent = function blockStylingIsPresent(state) {
|
|
42
|
+
var _state$selection2 = state.selection,
|
|
43
|
+
from = _state$selection2.from,
|
|
44
|
+
to = _state$selection2.to;
|
|
45
|
+
var isBlockStyling = false;
|
|
46
|
+
state.doc.nodesBetween(from, to, function (node) {
|
|
47
|
+
if (_clearFormatting.FORMATTING_NODE_TYPES.indexOf(node.type.name) !== -1) {
|
|
48
|
+
isBlockStyling = true;
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
});
|
|
53
|
+
return isBlockStyling;
|
|
54
|
+
};
|
|
55
|
+
var marksArePresent = function marksArePresent(state) {
|
|
56
|
+
var activeMarkTypes = _clearFormatting.FORMATTING_MARK_TYPES.filter(function (mark) {
|
|
57
|
+
if (!!state.schema.marks[mark]) {
|
|
58
|
+
var _state$selection3 = state.selection,
|
|
59
|
+
$from = _state$selection3.$from,
|
|
60
|
+
empty = _state$selection3.empty;
|
|
61
|
+
var marks = state.schema.marks;
|
|
62
|
+
if (empty) {
|
|
63
|
+
return !!marks[mark].isInSet(state.storedMarks || $from.marks());
|
|
64
|
+
}
|
|
65
|
+
return (0, _mark.anyMarkActive)(state, marks[mark]);
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
});
|
|
69
|
+
return activeMarkTypes.length > 0;
|
|
70
|
+
};
|
|
71
|
+
var checkFormattingIsPresent = function checkFormattingIsPresent(state) {
|
|
72
|
+
return marksArePresent(state) || blockStylingIsPresent(state);
|
|
73
|
+
};
|
|
74
|
+
exports.checkFormattingIsPresent = checkFormattingIsPresent;
|
|
75
|
+
var compareItemsArrays = function compareItemsArrays(items, prevItems) {
|
|
76
|
+
return items && items.filter(function (item) {
|
|
77
|
+
return !prevItems.includes(item);
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
exports.compareItemsArrays = compareItemsArrays;
|
|
81
|
+
var isArrayContainsContent = function isArrayContainsContent(items, content) {
|
|
82
|
+
return items.filter(function (item) {
|
|
83
|
+
return item.content === content;
|
|
84
|
+
}).length > 0;
|
|
85
|
+
};
|
|
86
|
+
exports.isArrayContainsContent = isArrayContainsContent;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
|
|
3
|
+
import { toggleMark } from '@atlaskit/editor-common/mark';
|
|
4
|
+
export const toggleEm = () => {
|
|
5
|
+
return (state, dispatch) => {
|
|
6
|
+
const {
|
|
7
|
+
em
|
|
8
|
+
} = state.schema.marks;
|
|
9
|
+
if (em) {
|
|
10
|
+
return toggleMark(em)(state, dispatch);
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export const toggleEmWithAnalytics = editorAnalyticsAPI => ({
|
|
16
|
+
inputMethod
|
|
17
|
+
}) => withAnalytics(editorAnalyticsAPI, {
|
|
18
|
+
action: ACTION.FORMATTED,
|
|
19
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
20
|
+
eventType: EVENT_TYPE.TRACK,
|
|
21
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_ITALIC,
|
|
22
|
+
attributes: {
|
|
23
|
+
inputMethod
|
|
24
|
+
}
|
|
25
|
+
})(toggleEm());
|
|
26
|
+
export const toggleStrike = () => {
|
|
27
|
+
return (state, dispatch) => {
|
|
28
|
+
const {
|
|
29
|
+
strike
|
|
30
|
+
} = state.schema.marks;
|
|
31
|
+
if (strike) {
|
|
32
|
+
return toggleMark(strike)(state, dispatch);
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export const toggleStrikeWithAnalytics = editorAnalyticsAPI => ({
|
|
38
|
+
inputMethod
|
|
39
|
+
}) => withAnalytics(editorAnalyticsAPI, {
|
|
40
|
+
action: ACTION.FORMATTED,
|
|
41
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
42
|
+
eventType: EVENT_TYPE.TRACK,
|
|
43
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_STRIKE,
|
|
44
|
+
attributes: {
|
|
45
|
+
inputMethod
|
|
46
|
+
}
|
|
47
|
+
})(toggleStrike());
|
|
48
|
+
export const toggleStrong = () => {
|
|
49
|
+
return (state, dispatch) => {
|
|
50
|
+
const {
|
|
51
|
+
strong
|
|
52
|
+
} = state.schema.marks;
|
|
53
|
+
if (strong) {
|
|
54
|
+
return toggleMark(strong)(state, dispatch);
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export const toggleStrongWithAnalytics = editorAnalyticsAPI => ({
|
|
60
|
+
inputMethod
|
|
61
|
+
}) => withAnalytics(editorAnalyticsAPI, {
|
|
62
|
+
action: ACTION.FORMATTED,
|
|
63
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
64
|
+
eventType: EVENT_TYPE.TRACK,
|
|
65
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_STRONG,
|
|
66
|
+
attributes: {
|
|
67
|
+
inputMethod
|
|
68
|
+
}
|
|
69
|
+
})(toggleStrong());
|
|
70
|
+
export const toggleUnderline = () => {
|
|
71
|
+
return (state, dispatch) => {
|
|
72
|
+
const {
|
|
73
|
+
underline
|
|
74
|
+
} = state.schema.marks;
|
|
75
|
+
if (underline) {
|
|
76
|
+
return toggleMark(underline)(state, dispatch);
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
export const toggleUnderlineWithAnalytics = editorAnalyticsAPI => ({
|
|
82
|
+
inputMethod
|
|
83
|
+
}) => withAnalytics(editorAnalyticsAPI, {
|
|
84
|
+
action: ACTION.FORMATTED,
|
|
85
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
86
|
+
eventType: EVENT_TYPE.TRACK,
|
|
87
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_UNDERLINE,
|
|
88
|
+
attributes: {
|
|
89
|
+
inputMethod
|
|
90
|
+
}
|
|
91
|
+
})(toggleUnderline());
|
|
92
|
+
export const toggleSuperscript = () => {
|
|
93
|
+
return (state, dispatch) => {
|
|
94
|
+
const {
|
|
95
|
+
subsup
|
|
96
|
+
} = state.schema.marks;
|
|
97
|
+
if (subsup) {
|
|
98
|
+
return toggleMark(subsup, {
|
|
99
|
+
type: 'sup'
|
|
100
|
+
})(state, dispatch);
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
export const toggleSuperscriptWithAnalytics = editorAnalyticsAPI => ({
|
|
106
|
+
inputMethod
|
|
107
|
+
}) => withAnalytics(editorAnalyticsAPI, {
|
|
108
|
+
action: ACTION.FORMATTED,
|
|
109
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
110
|
+
eventType: EVENT_TYPE.TRACK,
|
|
111
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_SUPER,
|
|
112
|
+
attributes: {
|
|
113
|
+
inputMethod
|
|
114
|
+
}
|
|
115
|
+
})(toggleSuperscript());
|
|
116
|
+
export const toggleSubscript = () => {
|
|
117
|
+
return (state, dispatch) => {
|
|
118
|
+
const {
|
|
119
|
+
subsup
|
|
120
|
+
} = state.schema.marks;
|
|
121
|
+
if (subsup) {
|
|
122
|
+
return toggleMark(subsup, {
|
|
123
|
+
type: 'sub'
|
|
124
|
+
})(state, dispatch);
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
export const toggleSubscriptWithAnalytics = editorAnalyticsAPI => ({
|
|
130
|
+
inputMethod
|
|
131
|
+
}) => withAnalytics(editorAnalyticsAPI, {
|
|
132
|
+
action: ACTION.FORMATTED,
|
|
133
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
134
|
+
eventType: EVENT_TYPE.TRACK,
|
|
135
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_SUB,
|
|
136
|
+
attributes: {
|
|
137
|
+
inputMethod
|
|
138
|
+
}
|
|
139
|
+
})(toggleSubscript());
|
|
140
|
+
export const toggleCode = () => {
|
|
141
|
+
return (state, dispatch) => {
|
|
142
|
+
const {
|
|
143
|
+
code
|
|
144
|
+
} = state.schema.marks;
|
|
145
|
+
if (code) {
|
|
146
|
+
return toggleMark(code)(state, dispatch);
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
export const toggleCodeWithAnalytics = editorAnalyticsAPI => ({
|
|
152
|
+
inputMethod
|
|
153
|
+
}) => withAnalytics(editorAnalyticsAPI, {
|
|
154
|
+
action: ACTION.FORMATTED,
|
|
155
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
156
|
+
eventType: EVENT_TYPE.TRACK,
|
|
157
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_CODE,
|
|
158
|
+
attributes: {
|
|
159
|
+
inputMethod
|
|
160
|
+
}
|
|
161
|
+
})(toggleCode());
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { liftTarget } from '@atlaskit/editor-prosemirror/transform';
|
|
3
|
+
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
4
|
+
import { cellSelectionNodesBetween } from '../utils/cell-selection';
|
|
5
|
+
export const FORMATTING_NODE_TYPES = ['heading', 'blockquote'];
|
|
6
|
+
export const FORMATTING_MARK_TYPES = ['em', 'code', 'strike', 'strong', 'underline', 'textColor', 'subsup'];
|
|
7
|
+
const formatTypes = {
|
|
8
|
+
em: ACTION_SUBJECT_ID.FORMAT_ITALIC,
|
|
9
|
+
code: ACTION_SUBJECT_ID.FORMAT_CODE,
|
|
10
|
+
strike: ACTION_SUBJECT_ID.FORMAT_STRIKE,
|
|
11
|
+
strong: ACTION_SUBJECT_ID.FORMAT_STRONG,
|
|
12
|
+
underline: ACTION_SUBJECT_ID.FORMAT_UNDERLINE,
|
|
13
|
+
textColor: ACTION_SUBJECT_ID.FORMAT_COLOR,
|
|
14
|
+
subsup: 'subsup'
|
|
15
|
+
};
|
|
16
|
+
export function clearFormattingWithAnalytics(inputMethod, editorAnalyticsAPI) {
|
|
17
|
+
return clearFormatting(inputMethod, editorAnalyticsAPI);
|
|
18
|
+
}
|
|
19
|
+
function clearNodeFormattingOnSelection(state, tr, formattedNodeType, nodeName, formattingCleared) {
|
|
20
|
+
return function (node, pos) {
|
|
21
|
+
if (node.type === formattedNodeType) {
|
|
22
|
+
if (formattedNodeType.isTextblock) {
|
|
23
|
+
tr.setNodeMarkup(pos, state.schema.nodes.paragraph);
|
|
24
|
+
formattingCleared.push(nodeName);
|
|
25
|
+
return false;
|
|
26
|
+
} else {
|
|
27
|
+
// In case of panel or blockquote
|
|
28
|
+
let fromPos = tr.doc.resolve(pos + 1);
|
|
29
|
+
let toPos = tr.doc.resolve(pos + node.nodeSize - 1);
|
|
30
|
+
const nodeRange = fromPos.blockRange(toPos);
|
|
31
|
+
if (nodeRange) {
|
|
32
|
+
const targetLiftDepth = liftTarget(nodeRange);
|
|
33
|
+
if (targetLiftDepth || targetLiftDepth === 0) {
|
|
34
|
+
formattingCleared.push(nodeName);
|
|
35
|
+
tr.lift(nodeRange, targetLiftDepth);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function clearFormatting(inputMethod, editorAnalyticsAPI) {
|
|
44
|
+
return function (state, dispatch) {
|
|
45
|
+
const {
|
|
46
|
+
tr
|
|
47
|
+
} = state;
|
|
48
|
+
const formattingCleared = [];
|
|
49
|
+
FORMATTING_MARK_TYPES.forEach(mark => {
|
|
50
|
+
const {
|
|
51
|
+
from,
|
|
52
|
+
to
|
|
53
|
+
} = tr.selection;
|
|
54
|
+
const markType = state.schema.marks[mark];
|
|
55
|
+
if (!markType) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (tr.selection instanceof CellSelection) {
|
|
59
|
+
cellSelectionNodesBetween(tr.selection, tr.doc, (node, pos) => {
|
|
60
|
+
const isTableCell = node.type === state.schema.nodes.tableCell || node.type === state.schema.nodes.tableHeader;
|
|
61
|
+
if (!isTableCell) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (tr.doc.rangeHasMark(pos, pos + node.nodeSize, markType)) {
|
|
65
|
+
formattingCleared.push(formatTypes[mark]);
|
|
66
|
+
tr.removeMark(pos, pos + node.nodeSize, markType);
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
});
|
|
70
|
+
} else if (tr.doc.rangeHasMark(from, to, markType)) {
|
|
71
|
+
formattingCleared.push(formatTypes[mark]);
|
|
72
|
+
tr.removeMark(from, to, markType);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
FORMATTING_NODE_TYPES.forEach(nodeName => {
|
|
76
|
+
const formattedNodeType = state.schema.nodes[nodeName];
|
|
77
|
+
const {
|
|
78
|
+
$from,
|
|
79
|
+
$to
|
|
80
|
+
} = tr.selection;
|
|
81
|
+
if (tr.selection instanceof CellSelection) {
|
|
82
|
+
cellSelectionNodesBetween(tr.selection, tr.doc, clearNodeFormattingOnSelection(state, tr, formattedNodeType, nodeName, formattingCleared));
|
|
83
|
+
} else {
|
|
84
|
+
tr.doc.nodesBetween($from.pos, $to.pos, clearNodeFormattingOnSelection(state, tr, formattedNodeType, nodeName, formattingCleared));
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
tr.setStoredMarks([]);
|
|
88
|
+
if (formattingCleared.length && inputMethod) {
|
|
89
|
+
editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent({
|
|
90
|
+
action: ACTION.FORMATTED,
|
|
91
|
+
eventType: EVENT_TYPE.TRACK,
|
|
92
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
93
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_CLEAR,
|
|
94
|
+
attributes: {
|
|
95
|
+
inputMethod,
|
|
96
|
+
formattingCleared
|
|
97
|
+
}
|
|
98
|
+
})(tr);
|
|
99
|
+
}
|
|
100
|
+
if (dispatch) {
|
|
101
|
+
dispatch(tr);
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
|
|
3
|
+
import { applyMarkOnRange } from '@atlaskit/editor-common/mark';
|
|
4
|
+
import { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
5
|
+
import { hasCode, markActive } from '../utils';
|
|
6
|
+
export const moveRight = () => {
|
|
7
|
+
return (state, dispatch) => {
|
|
8
|
+
const {
|
|
9
|
+
code
|
|
10
|
+
} = state.schema.marks;
|
|
11
|
+
const {
|
|
12
|
+
empty,
|
|
13
|
+
$cursor
|
|
14
|
+
} = state.selection;
|
|
15
|
+
if (!empty || !$cursor) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const {
|
|
19
|
+
storedMarks
|
|
20
|
+
} = state.tr;
|
|
21
|
+
if (code) {
|
|
22
|
+
const insideCode = markActive(state, code.create());
|
|
23
|
+
const currentPosHasCode = state.doc.rangeHasMark($cursor.pos, $cursor.pos, code);
|
|
24
|
+
const nextPosHasCode = state.doc.rangeHasMark($cursor.pos, $cursor.pos + 1, code);
|
|
25
|
+
const exitingCode = !currentPosHasCode && !nextPosHasCode && (!storedMarks || !!storedMarks.length);
|
|
26
|
+
const enteringCode = !currentPosHasCode && nextPosHasCode && (!storedMarks || !storedMarks.length);
|
|
27
|
+
|
|
28
|
+
// entering code mark (from the left edge): don't move the cursor, just add the mark
|
|
29
|
+
if (!insideCode && enteringCode) {
|
|
30
|
+
if (dispatch) {
|
|
31
|
+
dispatch(state.tr.addStoredMark(code.create()));
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// exiting code mark: don't move the cursor, just remove the mark
|
|
37
|
+
if (insideCode && exitingCode) {
|
|
38
|
+
if (dispatch) {
|
|
39
|
+
dispatch(state.tr.removeStoredMark(code));
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export const moveLeft = () => {
|
|
48
|
+
return (state, dispatch) => {
|
|
49
|
+
const {
|
|
50
|
+
code
|
|
51
|
+
} = state.schema.marks;
|
|
52
|
+
const {
|
|
53
|
+
empty,
|
|
54
|
+
$cursor
|
|
55
|
+
} = state.selection;
|
|
56
|
+
if (!empty || !$cursor) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const {
|
|
60
|
+
storedMarks
|
|
61
|
+
} = state.tr;
|
|
62
|
+
if (code) {
|
|
63
|
+
const insideCode = code && markActive(state, code.create());
|
|
64
|
+
const currentPosHasCode = hasCode(state, $cursor.pos);
|
|
65
|
+
const nextPosHasCode = hasCode(state, $cursor.pos - 1);
|
|
66
|
+
const nextNextPosHasCode = hasCode(state, $cursor.pos - 2);
|
|
67
|
+
const exitingCode = currentPosHasCode && !nextPosHasCode && Array.isArray(storedMarks);
|
|
68
|
+
const atLeftEdge = nextPosHasCode && !nextNextPosHasCode && (storedMarks === null || Array.isArray(storedMarks) && !!storedMarks.length);
|
|
69
|
+
const atRightEdge = (exitingCode && Array.isArray(storedMarks) && !storedMarks.length || !exitingCode && storedMarks === null) && !nextPosHasCode && nextNextPosHasCode;
|
|
70
|
+
const enteringCode = !currentPosHasCode && nextPosHasCode && Array.isArray(storedMarks) && !storedMarks.length;
|
|
71
|
+
|
|
72
|
+
// at the right edge: remove code mark and move the cursor to the left
|
|
73
|
+
if (!insideCode && atRightEdge) {
|
|
74
|
+
const tr = state.tr.setSelection(Selection.near(state.doc.resolve($cursor.pos - 1)));
|
|
75
|
+
if (dispatch) {
|
|
76
|
+
dispatch(tr.removeStoredMark(code));
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// entering code mark (from right edge): don't move the cursor, just add the mark
|
|
82
|
+
if (!insideCode && enteringCode) {
|
|
83
|
+
if (dispatch) {
|
|
84
|
+
dispatch(state.tr.addStoredMark(code.create()));
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// at the left edge: add code mark and move the cursor to the left
|
|
90
|
+
if (insideCode && atLeftEdge) {
|
|
91
|
+
const tr = state.tr.setSelection(Selection.near(state.doc.resolve($cursor.pos - 1)));
|
|
92
|
+
if (dispatch) {
|
|
93
|
+
dispatch(tr.addStoredMark(code.create()));
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// exiting code mark (or at the beginning of the line): don't move the cursor, just remove the mark
|
|
99
|
+
const isFirstChild = $cursor.index($cursor.depth - 1) === 0;
|
|
100
|
+
if (insideCode && (exitingCode || !$cursor.nodeBefore && isFirstChild)) {
|
|
101
|
+
if (dispatch) {
|
|
102
|
+
dispatch(state.tr.removeStoredMark(code));
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
const createInlineCodeFromTextInput = (from, to, text) => {
|
|
111
|
+
return (state, dispatch) => {
|
|
112
|
+
if (state.selection.empty) {
|
|
113
|
+
const {
|
|
114
|
+
nodeBefore: before
|
|
115
|
+
} = state.doc.resolve(from);
|
|
116
|
+
const {
|
|
117
|
+
nodeAfter: after
|
|
118
|
+
} = state.doc.resolve(to);
|
|
119
|
+
const hasTickBefore = before && before.text && before.text.endsWith('`');
|
|
120
|
+
const hasTickAfter = after && after.text && after.text.startsWith('`');
|
|
121
|
+
if (hasTickBefore && hasTickAfter) {
|
|
122
|
+
let tr = state.tr.replaceRangeWith(from - 1, to + 1, state.schema.text(text));
|
|
123
|
+
if (dispatch) {
|
|
124
|
+
const codeMark = state.schema.marks.code.create();
|
|
125
|
+
tr = applyMarkOnRange(tr.mapping.map(from - 1), tr.mapping.map(to + 1), false, codeMark, tr).setStoredMarks([codeMark]);
|
|
126
|
+
dispatch(tr);
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
export const createInlineCodeFromTextInputWithAnalytics = editorAnalyticsAPI => (from, to, text) => {
|
|
135
|
+
return withAnalytics(editorAnalyticsAPI, {
|
|
136
|
+
action: ACTION.FORMATTED,
|
|
137
|
+
actionSubject: ACTION_SUBJECT.TEXT,
|
|
138
|
+
eventType: EVENT_TYPE.TRACK,
|
|
139
|
+
actionSubjectId: ACTION_SUBJECT_ID.FORMAT_CODE,
|
|
140
|
+
attributes: {
|
|
141
|
+
inputMethod: INPUT_METHOD.FORMATTING
|
|
142
|
+
}
|
|
143
|
+
})(createInlineCodeFromTextInput(from, to, text));
|
|
144
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { filterChildrenBetween } from '@atlaskit/editor-common/mark';
|
|
2
|
+
const SMART_TO_ASCII = {
|
|
3
|
+
'…': '...',
|
|
4
|
+
'→': '->',
|
|
5
|
+
'←': '<-',
|
|
6
|
+
'–': '--',
|
|
7
|
+
'“': '"',
|
|
8
|
+
'”': '"',
|
|
9
|
+
'‘': "'",
|
|
10
|
+
'’': "'"
|
|
11
|
+
};
|
|
12
|
+
const FIND_SMART_CHAR = new RegExp(`[${Object.keys(SMART_TO_ASCII).join('')}]`, 'g');
|
|
13
|
+
const replaceMentionOrEmojiForTextContent = (position, nodeSize, textContent, tr) => {
|
|
14
|
+
const currentPos = tr.mapping.map(position);
|
|
15
|
+
const {
|
|
16
|
+
schema
|
|
17
|
+
} = tr.doc.type;
|
|
18
|
+
tr.replaceWith(currentPos, currentPos + nodeSize, schema.text(textContent));
|
|
19
|
+
};
|
|
20
|
+
const replaceSmartCharsToAscii = (position, textContent, tr) => {
|
|
21
|
+
const {
|
|
22
|
+
schema
|
|
23
|
+
} = tr.doc.type;
|
|
24
|
+
let match;
|
|
25
|
+
while (match = FIND_SMART_CHAR.exec(textContent)) {
|
|
26
|
+
const {
|
|
27
|
+
0: smartChar,
|
|
28
|
+
index: offset
|
|
29
|
+
} = match;
|
|
30
|
+
const replacePos = tr.mapping.map(position + offset);
|
|
31
|
+
const replacementText = schema.text(SMART_TO_ASCII[smartChar]);
|
|
32
|
+
tr.replaceWith(replacePos, replacePos + smartChar.length, replacementText);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const isNodeTextBlock = schema => {
|
|
36
|
+
const {
|
|
37
|
+
mention,
|
|
38
|
+
text,
|
|
39
|
+
emoji
|
|
40
|
+
} = schema.nodes;
|
|
41
|
+
return (node, _, parent) => {
|
|
42
|
+
if (node.type === mention || node.type === emoji || node.type === text) {
|
|
43
|
+
return parent === null || parent === void 0 ? void 0 : parent.isTextblock;
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export const transformSmartCharsMentionsAndEmojis = (from, to, tr) => {
|
|
49
|
+
const {
|
|
50
|
+
schema
|
|
51
|
+
} = tr.doc.type;
|
|
52
|
+
const {
|
|
53
|
+
mention,
|
|
54
|
+
text,
|
|
55
|
+
emoji
|
|
56
|
+
} = schema.nodes;
|
|
57
|
+
// Traverse through all the nodes within the range and replace them with their plaintext counterpart
|
|
58
|
+
const children = filterChildrenBetween(tr.doc, from, to, isNodeTextBlock(schema));
|
|
59
|
+
children.forEach(({
|
|
60
|
+
node,
|
|
61
|
+
pos
|
|
62
|
+
}) => {
|
|
63
|
+
if (node.type === mention || node.type === emoji) {
|
|
64
|
+
replaceMentionOrEmojiForTextContent(pos, node.nodeSize, node.attrs.text, tr);
|
|
65
|
+
} else if (node.type === text && node.text) {
|
|
66
|
+
const replacePosition = pos > from ? pos : from;
|
|
67
|
+
const textToReplace = pos > from ? node.text : node.text.substr(from - pos);
|
|
68
|
+
replaceSmartCharsToAscii(replacePosition, textToReplace, tr);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { textFormattingPlugin } from './plugin';
|