@atlaskit/editor-plugin-block-menu 6.0.33 → 6.0.34
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/CHANGELOG.md +10 -0
- package/dist/cjs/blockMenuPlugin.js +0 -4
- package/dist/cjs/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.js +11 -1
- package/dist/cjs/ui/block-menu-renderer/fallbacks.js +23 -16
- package/dist/es2019/blockMenuPlugin.js +0 -4
- package/dist/es2019/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.js +11 -1
- package/dist/es2019/ui/block-menu-renderer/fallbacks.js +21 -8
- package/dist/esm/blockMenuPlugin.js +0 -4
- package/dist/esm/editor-commands/transform-node-utils/steps/applyTargetTextTypeStep.js +11 -1
- package/dist/esm/ui/block-menu-renderer/fallbacks.js +23 -16
- package/dist/types/blockMenuPluginType.d.ts +1 -3
- package/dist/types/editor-commands/selection.d.ts +2 -2
- package/dist/types/editor-commands/transforms/transformNodeToTargetType.d.ts +2 -2
- package/dist/types/editor-commands/transforms/types.d.ts +3 -6
- package/dist/types/editor-commands/transforms/utils.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types-ts4.5/blockMenuPluginType.d.ts +1 -3
- package/dist/types-ts4.5/editor-commands/selection.d.ts +2 -2
- package/dist/types-ts4.5/editor-commands/transforms/transformNodeToTargetType.d.ts +2 -2
- package/dist/types-ts4.5/editor-commands/transforms/types.d.ts +3 -6
- package/dist/types-ts4.5/editor-commands/transforms/utils.d.ts +2 -2
- package/dist/types-ts4.5/index.d.ts +1 -1
- package/package.json +2 -2
- package/dist/cjs/editor-commands/formatNode.js +0 -268
- package/dist/es2019/editor-commands/formatNode.js +0 -272
- package/dist/esm/editor-commands/formatNode.js +0 -263
- package/dist/types/editor-commands/formatNode.d.ts +0 -20
- package/dist/types-ts4.5/editor-commands/formatNode.d.ts +0 -20
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
|
-
import { logException } from '@atlaskit/editor-common/monitoring';
|
|
3
|
-
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
-
import { findParentNodeOfType, findSelectedNodeOfType, safeInsert as pmSafeInsert } from '@atlaskit/editor-prosemirror/utils';
|
|
5
|
-
import { setSelectionAfterTransform } from './selection';
|
|
6
|
-
import { createDefaultLayoutSection } from './transforms/layout-transforms';
|
|
7
|
-
import { transformNodeToTargetType } from './transforms/transformNodeToTargetType';
|
|
8
|
-
import { isListNodeType, getConversionType } from './transforms/utils';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Handles formatting when selection is empty by inserting a new target node
|
|
12
|
-
*/
|
|
13
|
-
var formatNodeWhenSelectionEmpty = function formatNodeWhenSelectionEmpty(tr, targetType, nodePos, schema) {
|
|
14
|
-
var _pmSafeInsert;
|
|
15
|
-
var nodes = schema.nodes;
|
|
16
|
-
var paragraph = nodes.paragraph;
|
|
17
|
-
// if not using the ' ' here, the safeInsert from editor-common will fail to insert the heading
|
|
18
|
-
// and the pmSafeInsert introduce an issue that after inserting heading, and click on the handle, selection will go to top of the doc
|
|
19
|
-
// as an workaround, use the spaceTextNode here
|
|
20
|
-
var spaceTextNode = schema.text(' ');
|
|
21
|
-
var targetNode;
|
|
22
|
-
if (targetType.startsWith('heading')) {
|
|
23
|
-
var levelString = targetType.slice(-1);
|
|
24
|
-
var level = parseInt(levelString, 10);
|
|
25
|
-
if (isNaN(level) || level < 1 || level > 6) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
targetNode = nodes.heading.createAndFill({
|
|
29
|
-
level: level
|
|
30
|
-
}, spaceTextNode);
|
|
31
|
-
} else if (targetType === 'paragraph') {
|
|
32
|
-
targetNode = nodes.paragraph.createAndFill({}, spaceTextNode);
|
|
33
|
-
} else if (targetType === 'layoutSection') {
|
|
34
|
-
var contentAsParagraph = paragraph.createAndFill({}, spaceTextNode);
|
|
35
|
-
if (contentAsParagraph) {
|
|
36
|
-
targetNode = createDefaultLayoutSection(schema, contentAsParagraph);
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
var targetNodeType = nodes[targetType];
|
|
40
|
-
targetNode = targetNodeType.createAndFill();
|
|
41
|
-
}
|
|
42
|
-
if (!targetNode) {
|
|
43
|
-
return tr;
|
|
44
|
-
}
|
|
45
|
-
tr = (_pmSafeInsert = pmSafeInsert(targetNode, nodePos)(tr)) !== null && _pmSafeInsert !== void 0 ? _pmSafeInsert : tr;
|
|
46
|
-
return tr;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Handles formatting when an empty list is selected
|
|
51
|
-
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
52
|
-
*/
|
|
53
|
-
export var formatNodeSelectEmptyList = function formatNodeSelectEmptyList(tr, targetType, listNode, schema) {
|
|
54
|
-
var nodes = schema.nodes;
|
|
55
|
-
var headingLevel = 1;
|
|
56
|
-
var finalTargetType = targetType;
|
|
57
|
-
if (targetType.startsWith('heading')) {
|
|
58
|
-
var levelString = targetType.slice(-1);
|
|
59
|
-
var level = parseInt(levelString, 10);
|
|
60
|
-
if (!isNaN(level) && level >= 1 && level <= 6) {
|
|
61
|
-
headingLevel = level;
|
|
62
|
-
finalTargetType = 'heading';
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
var replaceNode = null;
|
|
66
|
-
if (finalTargetType === 'layoutSection') {
|
|
67
|
-
var emptyPara = nodes.paragraph.createAndFill();
|
|
68
|
-
if (emptyPara) {
|
|
69
|
-
replaceNode = createDefaultLayoutSection(schema, emptyPara);
|
|
70
|
-
}
|
|
71
|
-
} else if (finalTargetType === 'heading') {
|
|
72
|
-
replaceNode = nodes.heading.createAndFill({
|
|
73
|
-
level: headingLevel
|
|
74
|
-
});
|
|
75
|
-
} else {
|
|
76
|
-
replaceNode = nodes[finalTargetType].createAndFill();
|
|
77
|
-
}
|
|
78
|
-
if (replaceNode) {
|
|
79
|
-
tr.replaceWith(listNode.pos, listNode.pos + listNode.node.nodeSize, replaceNode);
|
|
80
|
-
tr.setSelection(new TextSelection(tr.doc.resolve(listNode.pos)));
|
|
81
|
-
}
|
|
82
|
-
return tr;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Formats the current node or selection to the specified target type
|
|
87
|
-
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
|
88
|
-
* @param targetType - The target node type to convert to
|
|
89
|
-
* @param analyticsAttrs - Attributes required for formatNode analytics like: inputMethod and triggeredFrom
|
|
90
|
-
*/
|
|
91
|
-
export var formatNode = function formatNode(api) {
|
|
92
|
-
return function (targetType, analyticsAttrs) {
|
|
93
|
-
return function (_ref) {
|
|
94
|
-
var tr = _ref.tr;
|
|
95
|
-
var selection = tr.selection;
|
|
96
|
-
var schema = tr.doc.type.schema;
|
|
97
|
-
var nodes = schema.nodes;
|
|
98
|
-
|
|
99
|
-
// Find the node to format from the current selection
|
|
100
|
-
var nodeToFormat;
|
|
101
|
-
var nodePos = selection.from;
|
|
102
|
-
|
|
103
|
-
// when selection is empty, we insert a empty target node
|
|
104
|
-
if (selection.empty) {
|
|
105
|
-
var listNodes = [];
|
|
106
|
-
// need to find if there is any list node in the current selection
|
|
107
|
-
// As when select a empty list, selection is empty, but we want to convert the list instead of inserting a target node
|
|
108
|
-
// findSelectedNodeOfType does not work when selection is empty, so we use nodesBetween
|
|
109
|
-
tr.doc.nodesBetween(selection.from, selection.to, function (node, pos) {
|
|
110
|
-
if (isListNodeType(node.type)) {
|
|
111
|
-
listNodes.push({
|
|
112
|
-
node: node,
|
|
113
|
-
pos: pos
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
// get the first list node as when click on drag handle if there are list node
|
|
118
|
-
// can only select one list at a time, so we just need to find the first one
|
|
119
|
-
if (listNodes.length > 0) {
|
|
120
|
-
var firstChild = listNodes[0];
|
|
121
|
-
var newTr = formatNodeSelectEmptyList(tr, targetType, firstChild, schema);
|
|
122
|
-
if (newTr) {
|
|
123
|
-
var _api$analytics;
|
|
124
|
-
var sourceTypeName = firstChild.node.type.name;
|
|
125
|
-
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent({
|
|
126
|
-
action: ACTION.CONVERTED,
|
|
127
|
-
actionSubject: ACTION_SUBJECT.ELEMENT,
|
|
128
|
-
eventType: EVENT_TYPE.TRACK,
|
|
129
|
-
attributes: {
|
|
130
|
-
from: sourceTypeName,
|
|
131
|
-
to: targetType,
|
|
132
|
-
eventCategory: getConversionType(sourceTypeName, targetType),
|
|
133
|
-
triggeredFrom: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.triggeredFrom) || INPUT_METHOD.MOUSE,
|
|
134
|
-
inputMethod: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.inputMethod) || INPUT_METHOD.BLOCK_MENU,
|
|
135
|
-
conversionSource: 'emptyList'
|
|
136
|
-
}
|
|
137
|
-
})(newTr);
|
|
138
|
-
}
|
|
139
|
-
return newTr;
|
|
140
|
-
} else {
|
|
141
|
-
var _newTr = formatNodeWhenSelectionEmpty(tr, targetType, nodePos, schema);
|
|
142
|
-
var allowedNodes = [nodes.blockquote, nodes.panel, nodes.codeBlock, nodes.layoutSection, nodes.expand];
|
|
143
|
-
var _sourceTypeName = 'paragraph';
|
|
144
|
-
var conversionSource;
|
|
145
|
-
var containerNode = findParentNodeOfType(allowedNodes)(selection);
|
|
146
|
-
var paragraphOrHeading = findParentNodeOfType([nodes.heading, nodes.paragraph])(selection);
|
|
147
|
-
if (containerNode) {
|
|
148
|
-
// At the moment this branch is executed for converstions from an empty blockquote
|
|
149
|
-
_sourceTypeName = containerNode.node.type.name;
|
|
150
|
-
conversionSource = undefined; // could be 'emptyNode' or something else
|
|
151
|
-
} else if (paragraphOrHeading) {
|
|
152
|
-
_sourceTypeName = paragraphOrHeading.node.type.name;
|
|
153
|
-
if (_sourceTypeName === 'heading') {
|
|
154
|
-
_sourceTypeName = "heading".concat(paragraphOrHeading.node.attrs.level);
|
|
155
|
-
}
|
|
156
|
-
conversionSource = 'emptyLine';
|
|
157
|
-
}
|
|
158
|
-
if (_newTr) {
|
|
159
|
-
var _api$analytics2;
|
|
160
|
-
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.attachAnalyticsEvent({
|
|
161
|
-
action: ACTION.CONVERTED,
|
|
162
|
-
actionSubject: ACTION_SUBJECT.ELEMENT,
|
|
163
|
-
eventType: EVENT_TYPE.TRACK,
|
|
164
|
-
attributes: {
|
|
165
|
-
from: _sourceTypeName,
|
|
166
|
-
to: targetType,
|
|
167
|
-
eventCategory: getConversionType(_sourceTypeName, targetType),
|
|
168
|
-
triggeredFrom: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.triggeredFrom) || INPUT_METHOD.MOUSE,
|
|
169
|
-
inputMethod: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.inputMethod) || INPUT_METHOD.BLOCK_MENU,
|
|
170
|
-
conversionSource: conversionSource
|
|
171
|
-
}
|
|
172
|
-
})(_newTr);
|
|
173
|
-
}
|
|
174
|
-
return _newTr;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Try to find the current node from selection
|
|
179
|
-
var selectedNode = findSelectedNodeOfType([nodes.paragraph, nodes.heading, nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.layoutSection])(selection);
|
|
180
|
-
if (selectedNode) {
|
|
181
|
-
nodeToFormat = selectedNode.node;
|
|
182
|
-
nodePos = selectedNode.pos;
|
|
183
|
-
} else {
|
|
184
|
-
// Try to find parent node (including list parents)
|
|
185
|
-
var parentNode = findParentNodeOfType([nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.listItem, nodes.taskItem, nodes.layoutSection])(selection);
|
|
186
|
-
if (parentNode) {
|
|
187
|
-
nodeToFormat = parentNode.node;
|
|
188
|
-
nodePos = parentNode.pos;
|
|
189
|
-
var paragraphOrHeadingNode = findParentNodeOfType([nodes.paragraph, nodes.heading])(selection);
|
|
190
|
-
// Special case: if we found a listItem, check if we need the parent list instead
|
|
191
|
-
if (parentNode.node.type === nodes.listItem || parentNode.node.type === nodes.taskItem) {
|
|
192
|
-
var listParent = findParentNodeOfType([nodes.bulletList, nodes.orderedList, nodes.taskList])(selection);
|
|
193
|
-
if (listParent) {
|
|
194
|
-
// For list transformations, we want the list parent, not the listItem
|
|
195
|
-
nodeToFormat = listParent.node;
|
|
196
|
-
nodePos = listParent.pos;
|
|
197
|
-
}
|
|
198
|
-
} else if (parentNode.node.type !== nodes.blockquote && paragraphOrHeadingNode) {
|
|
199
|
-
nodeToFormat = paragraphOrHeadingNode.node;
|
|
200
|
-
nodePos = paragraphOrHeadingNode.pos;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (!nodeToFormat) {
|
|
205
|
-
nodeToFormat = selection.$from.node();
|
|
206
|
-
nodePos = selection.$from.pos;
|
|
207
|
-
}
|
|
208
|
-
try {
|
|
209
|
-
var _nodeToFormat$attrs;
|
|
210
|
-
var _newTr2 = transformNodeToTargetType(tr, nodeToFormat, nodePos, targetType);
|
|
211
|
-
var _sourceTypeName2 = nodeToFormat.type.name;
|
|
212
|
-
if (_sourceTypeName2 === 'heading' && (_nodeToFormat$attrs = nodeToFormat.attrs) !== null && _nodeToFormat$attrs !== void 0 && _nodeToFormat$attrs.level) {
|
|
213
|
-
_sourceTypeName2 = "heading".concat(nodeToFormat.attrs.level);
|
|
214
|
-
}
|
|
215
|
-
if (_newTr2 && _sourceTypeName2 !== targetType) {
|
|
216
|
-
var _api$analytics3;
|
|
217
|
-
api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || (_api$analytics3 = _api$analytics3.actions) === null || _api$analytics3 === void 0 || _api$analytics3.attachAnalyticsEvent({
|
|
218
|
-
action: ACTION.CONVERTED,
|
|
219
|
-
actionSubject: ACTION_SUBJECT.ELEMENT,
|
|
220
|
-
eventType: EVENT_TYPE.TRACK,
|
|
221
|
-
attributes: {
|
|
222
|
-
from: _sourceTypeName2,
|
|
223
|
-
to: targetType,
|
|
224
|
-
eventCategory: getConversionType(_sourceTypeName2, targetType),
|
|
225
|
-
triggeredFrom: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.triggeredFrom) || INPUT_METHOD.MOUSE,
|
|
226
|
-
inputMethod: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.inputMethod) || INPUT_METHOD.BLOCK_MENU
|
|
227
|
-
}
|
|
228
|
-
})(_newTr2);
|
|
229
|
-
}
|
|
230
|
-
return _newTr2 ? setSelectionAfterTransform(_newTr2, nodePos, targetType) : _newTr2;
|
|
231
|
-
} catch (error) {
|
|
232
|
-
var _nodeToFormat$attrs2, _api$analytics4;
|
|
233
|
-
logException(error, {
|
|
234
|
-
location: 'editor-plugin-block-menu'
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
// Fire error analytics event
|
|
238
|
-
var _sourceTypeName3 = nodeToFormat.type.name;
|
|
239
|
-
if (_sourceTypeName3 === 'heading' && (_nodeToFormat$attrs2 = nodeToFormat.attrs) !== null && _nodeToFormat$attrs2 !== void 0 && _nodeToFormat$attrs2.level) {
|
|
240
|
-
_sourceTypeName3 = "heading".concat(nodeToFormat.attrs.level);
|
|
241
|
-
}
|
|
242
|
-
api === null || api === void 0 || (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 || (_api$analytics4 = _api$analytics4.actions) === null || _api$analytics4 === void 0 || _api$analytics4.fireAnalyticsEvent({
|
|
243
|
-
action: ACTION.ERRORED,
|
|
244
|
-
actionSubject: ACTION_SUBJECT.ELEMENT,
|
|
245
|
-
actionSubjectId: ACTION_SUBJECT_ID.TRANSFORM,
|
|
246
|
-
eventType: EVENT_TYPE.OPERATIONAL,
|
|
247
|
-
attributes: {
|
|
248
|
-
error: error.message,
|
|
249
|
-
errorStack: error.stack,
|
|
250
|
-
docSize: tr.doc.nodeSize,
|
|
251
|
-
from: _sourceTypeName3,
|
|
252
|
-
to: targetType,
|
|
253
|
-
position: tr.selection.from,
|
|
254
|
-
selection: tr.selection.toJSON(),
|
|
255
|
-
inputMethod: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.inputMethod) || INPUT_METHOD.BLOCK_MENU,
|
|
256
|
-
triggeredFrom: (analyticsAttrs === null || analyticsAttrs === void 0 ? void 0 : analyticsAttrs.triggeredFrom) || INPUT_METHOD.MOUSE
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
return null;
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
};
|
|
263
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
|
-
import { type Schema, type Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
-
import { type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
-
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
5
|
-
import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType } from './transforms/types';
|
|
6
|
-
/**
|
|
7
|
-
* Handles formatting when an empty list is selected
|
|
8
|
-
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
9
|
-
*/
|
|
10
|
-
export declare const formatNodeSelectEmptyList: (tr: Transaction, targetType: FormatNodeTargetType, listNode: {
|
|
11
|
-
node: PMNode;
|
|
12
|
-
pos: number;
|
|
13
|
-
}, schema: Schema) => Transaction;
|
|
14
|
-
/**
|
|
15
|
-
* Formats the current node or selection to the specified target type
|
|
16
|
-
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
|
17
|
-
* @param targetType - The target node type to convert to
|
|
18
|
-
* @param analyticsAttrs - Attributes required for formatNode analytics like: inputMethod and triggeredFrom
|
|
19
|
-
*/
|
|
20
|
-
export declare const formatNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { EditorCommand, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
2
|
-
import { type Schema, type Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
-
import { type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
-
import type { BlockMenuPlugin } from '../blockMenuPluginType';
|
|
5
|
-
import type { FormatNodeAnalyticsAttrs, FormatNodeTargetType } from './transforms/types';
|
|
6
|
-
/**
|
|
7
|
-
* Handles formatting when an empty list is selected
|
|
8
|
-
* Converting an empty list to a target node, will remove the list and replace with an empty target node
|
|
9
|
-
*/
|
|
10
|
-
export declare const formatNodeSelectEmptyList: (tr: Transaction, targetType: FormatNodeTargetType, listNode: {
|
|
11
|
-
node: PMNode;
|
|
12
|
-
pos: number;
|
|
13
|
-
}, schema: Schema) => Transaction;
|
|
14
|
-
/**
|
|
15
|
-
* Formats the current node or selection to the specified target type
|
|
16
|
-
* @param api - The editor API injection that provides access to analytics and other plugin actions
|
|
17
|
-
* @param targetType - The target node type to convert to
|
|
18
|
-
* @param analyticsAttrs - Attributes required for formatNode analytics like: inputMethod and triggeredFrom
|
|
19
|
-
*/
|
|
20
|
-
export declare const formatNode: (api?: ExtractInjectionAPI<BlockMenuPlugin>) => (targetType: FormatNodeTargetType, analyticsAttrs?: FormatNodeAnalyticsAttrs) => EditorCommand;
|