@azure/communication-react 1.5.1-alpha-202305040013 → 1.5.1-alpha-202305060013
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/communication-react.d.ts +84 -67
- package/dist/dist-cjs/communication-react/index.js +1460 -185
- package/dist/dist-cjs/communication-react/index.js.map +1 -1
- package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
- package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
- package/dist/dist-esm/communication-react/src/index.d.ts +1 -1
- package/dist/dist-esm/communication-react/src/index.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponent.d.ts +3 -3
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponent.js +7 -2
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponent.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsEditBox.d.ts +2 -0
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsEditBox.js +5 -1
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsEditBox.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsMessageBubble.d.ts +4 -4
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsMessageBubble.js +3 -1
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageComponentAsMessageBubble.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageContent.d.ts +2 -2
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageContent.js +56 -35
- package/dist/dist-esm/react-components/src/components/ChatMessage/ChatMessageContent.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/ChatMessage/MentionRenderer.d.ts +10 -0
- package/dist/dist-esm/react-components/src/components/ChatMessage/MentionRenderer.js +15 -0
- package/dist/dist-esm/react-components/src/components/ChatMessage/MentionRenderer.js.map +1 -0
- package/dist/dist-esm/react-components/src/components/InputBoxComponent.d.ts +3 -3
- package/dist/dist-esm/react-components/src/components/InputBoxComponent.js +1038 -5
- package/dist/dist-esm/react-components/src/components/InputBoxComponent.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/MentionPopover.d.ts +121 -0
- package/dist/dist-esm/react-components/src/components/MentionPopover.js +125 -0
- package/dist/dist-esm/react-components/src/components/MentionPopover.js.map +1 -0
- package/dist/dist-esm/react-components/src/components/MessageThread.d.ts +4 -4
- package/dist/dist-esm/react-components/src/components/MessageThread.js +9 -3
- package/dist/dist-esm/react-components/src/components/MessageThread.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/SendBox.d.ts +7 -7
- package/dist/dist-esm/react-components/src/components/SendBox.js +15 -9
- package/dist/dist-esm/react-components/src/components/SendBox.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/index.d.ts +2 -2
- package/dist/dist-esm/react-components/src/components/index.js +2 -2
- package/dist/dist-esm/react-components/src/components/index.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/styles/{AtMentionFlyout.style.d.ts → MentionPopover.style.d.ts} +4 -4
- package/dist/dist-esm/react-components/src/components/styles/{AtMentionFlyout.style.js → MentionPopover.style.js} +11 -13
- package/dist/dist-esm/react-components/src/components/styles/MentionPopover.style.js.map +1 -0
- package/dist/dist-esm/react-components/src/components/styles/MessageThread.styles.js +5 -1
- package/dist/dist-esm/react-components/src/components/styles/MessageThread.styles.js.map +1 -1
- package/dist/dist-esm/react-components/src/identifiers/IdentifierProvider.d.ts +4 -4
- package/dist/dist-esm/react-components/src/identifiers/IdentifierProvider.js +4 -4
- package/dist/dist-esm/react-components/src/identifiers/IdentifierProvider.js.map +1 -1
- package/dist/dist-esm/react-components/src/localization/LocalizationProvider.d.ts +3 -0
- package/dist/dist-esm/react-components/src/localization/LocalizationProvider.js.map +1 -1
- package/dist/dist-esm/react-components/src/localization/locales/en-US/strings.json +3 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/components/CallArrangement.js +8 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/components/CallArrangement.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/components/SidePane/useVideoEffectsPane.js +26 -3
- package/dist/dist-esm/react-composites/src/composites/CallComposite/components/SidePane/useVideoEffectsPane.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/ConfigurationPage.js +6 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/ConfigurationPage.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/videoBackgroundErrorsSelector.d.ts +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/videoBackgroundErrorsSelector.js +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/videoBackgroundErrorsSelector.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.d.ts +12 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js +13 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/common/VideoEffectsPane.d.ts +5 -1
- package/dist/dist-esm/react-composites/src/composites/common/VideoEffectsPane.js +5 -24
- package/dist/dist-esm/react-composites/src/composites/common/VideoEffectsPane.js.map +1 -1
- package/package.json +13 -11
- package/dist/dist-esm/react-components/src/components/AtMentionFlyout.d.ts +0 -91
- package/dist/dist-esm/react-components/src/components/AtMentionFlyout.js +0 -58
- package/dist/dist-esm/react-components/src/components/AtMentionFlyout.js.map +0 -1
- package/dist/dist-esm/react-components/src/components/styles/AtMentionFlyout.style.js.map +0 -1
@@ -1,15 +1,83 @@
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
2
2
|
// Licensed under the MIT license.
|
3
|
-
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
10
|
+
});
|
11
|
+
};
|
12
|
+
import React, { useState, useCallback, useRef } from 'react';
|
13
|
+
/* @conditional-compile-remove(mention) */
|
14
|
+
import { useEffect } from 'react';
|
15
|
+
/* @conditional-compile-remove(mention) */
|
16
|
+
import { useLocale } from '../localization';
|
4
17
|
import { Stack, TextField, mergeStyles, concatStyleSets, IconButton, TooltipHost } from '@fluentui/react';
|
5
18
|
import { inputBoxStyle, inputBoxWrapperStyle, inputButtonStyle, textFieldStyle, textContainerStyle, inlineButtonsContainerStyle, newLineButtonsContainerStyle, inputBoxNewLineSpaceAffordance, inputButtonTooltipStyle } from './styles/InputBoxComponent.style';
|
19
|
+
/* @conditional-compile-remove(mention) */
|
20
|
+
import { Caret } from 'textarea-caret-ts';
|
6
21
|
import { isDarkThemed } from '../theming/themeUtils';
|
7
22
|
import { useTheme } from '../theming';
|
23
|
+
/* @conditional-compile-remove(mention) */
|
24
|
+
import { _MentionPopover } from './MentionPopover';
|
25
|
+
/* @conditional-compile-remove(mention) */
|
26
|
+
import { useDebouncedCallback } from 'use-debounce';
|
27
|
+
/* @conditional-compile-remove(mention) */
|
28
|
+
const defaultMentionTrigger = '@';
|
8
29
|
/**
|
9
30
|
* @private
|
10
31
|
*/
|
11
32
|
export const InputBoxComponent = (props) => {
|
12
|
-
const { styles, id, 'data-ui-id': dataUiId, textValue, onChange, textFieldRef, placeholderText, onKeyDown, onEnterKeyDown, supportNewline, inputClassName, errorMessage, disabled, children
|
33
|
+
const { styles, id, 'data-ui-id': dataUiId, textValue, onChange, textFieldRef, placeholderText, onKeyDown, onEnterKeyDown, supportNewline, inputClassName, errorMessage, disabled, children,
|
34
|
+
/* @conditional-compile-remove(mention) */
|
35
|
+
mentionLookupOptions } = props;
|
36
|
+
const inputBoxRef = useRef(null);
|
37
|
+
/* @conditional-compile-remove(mention) */
|
38
|
+
// Current suggestion list, provided by the callback
|
39
|
+
const [mentionSuggestions, setMentionSuggestions] = useState([]);
|
40
|
+
/* @conditional-compile-remove(mention) */
|
41
|
+
// Current suggestion list, provided by the callback
|
42
|
+
const [activeSuggestionIndex, setActiveSuggestionIndex] = useState(undefined);
|
43
|
+
/* @conditional-compile-remove(mention) */
|
44
|
+
// Index of the current trigger character in the text field
|
45
|
+
const [currentTriggerStartIndex, setCurrentTriggerStartIndex] = useState(-1);
|
46
|
+
/* @conditional-compile-remove(mention) */
|
47
|
+
const [inputTextValue, setInputTextValue] = useState('');
|
48
|
+
/* @conditional-compile-remove(mention) */
|
49
|
+
const [tagsValue, setTagsValue] = useState([]);
|
50
|
+
/* @conditional-compile-remove(mention) */
|
51
|
+
const [selectionStartValue, setSelectionStartValue] = useState(null);
|
52
|
+
/* @conditional-compile-remove(mention) */
|
53
|
+
const [selectionEndValue, setSelectionEndValue] = useState(null);
|
54
|
+
/* @conditional-compile-remove(mention) */
|
55
|
+
const [shouldHandleOnMouseDownDuringSelect, setShouldHandleOnMouseDownDuringSelect] = useState(true);
|
56
|
+
/* @conditional-compile-remove(mention) */
|
57
|
+
// Caret position in the text field
|
58
|
+
const [caretPosition, setCaretPosition] = useState(undefined);
|
59
|
+
/* @conditional-compile-remove(mention) */
|
60
|
+
// Index of where the caret is in the text field
|
61
|
+
const [caretIndex, setCaretIndex] = useState(undefined);
|
62
|
+
/* @conditional-compile-remove(mention) */
|
63
|
+
const localeStrings = useLocale().strings;
|
64
|
+
/* @conditional-compile-remove(mention) */
|
65
|
+
const updateMentionSuggestions = useCallback((suggestions) => {
|
66
|
+
var _a;
|
67
|
+
setMentionSuggestions(suggestions);
|
68
|
+
if (caretIndex !== undefined) {
|
69
|
+
(_a = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _a === void 0 ? void 0 : _a.setSelectionEnd(caretIndex);
|
70
|
+
}
|
71
|
+
}, [textFieldRef, caretIndex]);
|
72
|
+
/* @conditional-compile-remove(mention) */
|
73
|
+
// Parse the text and get the plain text version to display in the input box
|
74
|
+
useEffect(() => {
|
75
|
+
const trigger = (mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) || defaultMentionTrigger;
|
76
|
+
const [tags, plainText] = textToTagParser(textValue, trigger);
|
77
|
+
setInputTextValue(plainText);
|
78
|
+
setTagsValue(tags);
|
79
|
+
updateMentionSuggestions([]);
|
80
|
+
}, [textValue, mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger, updateMentionSuggestions]);
|
13
81
|
const mergedRootStyle = mergeStyles(inputBoxWrapperStyle, styles === null || styles === void 0 ? void 0 : styles.root);
|
14
82
|
const mergedTextFiledStyle = mergeStyles(inputBoxStyle, inputClassName, props.inlineChildren ? {} : inputBoxNewLineSpaceAffordance);
|
15
83
|
const mergedTextContainerStyle = mergeStyles(textContainerStyle, styles === null || styles === void 0 ? void 0 : styles.textFieldContainer);
|
@@ -17,20 +85,309 @@ export const InputBoxComponent = (props) => {
|
|
17
85
|
fieldGroup: styles === null || styles === void 0 ? void 0 : styles.textField,
|
18
86
|
errorMessage: styles === null || styles === void 0 ? void 0 : styles.systemMessage
|
19
87
|
});
|
20
|
-
|
88
|
+
/* @conditional-compile-remove(mention) */
|
89
|
+
const onSuggestionSelected = useCallback((suggestion) => {
|
90
|
+
var _a, _b;
|
91
|
+
let selectionEnd = ((_a = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _a === void 0 ? void 0 : _a.selectionEnd) || -1;
|
92
|
+
if (selectionEnd < 0) {
|
93
|
+
selectionEnd = 0;
|
94
|
+
}
|
95
|
+
else if (selectionEnd > inputTextValue.length) {
|
96
|
+
selectionEnd = inputTextValue.length;
|
97
|
+
}
|
98
|
+
const oldPlainText = inputTextValue;
|
99
|
+
const mention = htmlStringForMentionSuggestion(suggestion, localeStrings);
|
100
|
+
// update plain text with the mention html text
|
101
|
+
const newPlainText = inputTextValue.substring(0, currentTriggerStartIndex) + mention + inputTextValue.substring(selectionEnd);
|
102
|
+
const triggerText = (_b = mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) !== null && _b !== void 0 ? _b : defaultMentionTrigger;
|
103
|
+
// update html text with updated plain text
|
104
|
+
const [updatedHTML] = updateHTML(textValue, oldPlainText, newPlainText, tagsValue, currentTriggerStartIndex, selectionEnd, mention, triggerText);
|
105
|
+
const displayName = getDisplayNameForMentionSuggestion(suggestion, localeStrings);
|
106
|
+
// Move the caret in the text field to the end of the mention plain text
|
107
|
+
setCaretIndex(selectionEnd + displayName.length);
|
108
|
+
setCurrentTriggerStartIndex(-1);
|
109
|
+
updateMentionSuggestions([]);
|
110
|
+
setActiveSuggestionIndex(undefined);
|
111
|
+
onChange && onChange(undefined, updatedHTML);
|
112
|
+
}, [
|
113
|
+
textFieldRef,
|
114
|
+
inputTextValue,
|
115
|
+
currentTriggerStartIndex,
|
116
|
+
mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger,
|
117
|
+
onChange,
|
118
|
+
textValue,
|
119
|
+
tagsValue,
|
120
|
+
/* @conditional-compile-remove(mention) */
|
121
|
+
updateMentionSuggestions,
|
122
|
+
/* @conditional-compile-remove(mention) */
|
123
|
+
localeStrings
|
124
|
+
]);
|
125
|
+
const onTextFieldKeyDown = useCallback((ev) => {
|
21
126
|
// Uses KeyCode 229 and which code 229 to determine if the press of the enter key is from a composition session or not (Safari only)
|
22
127
|
if (ev.nativeEvent.isComposing || ev.nativeEvent.keyCode === 229 || ev.nativeEvent.which === 229) {
|
23
128
|
return;
|
24
129
|
}
|
130
|
+
if (ev.key === 'ArrowUp') {
|
131
|
+
ev.preventDefault();
|
132
|
+
/* @conditional-compile-remove(mention) */
|
133
|
+
if (mentionSuggestions.length > 0) {
|
134
|
+
const newActiveIndex = activeSuggestionIndex === undefined
|
135
|
+
? mentionSuggestions.length - 1
|
136
|
+
: Math.max(activeSuggestionIndex - 1, 0);
|
137
|
+
setActiveSuggestionIndex(newActiveIndex);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
else if (ev.key === 'ArrowDown') {
|
141
|
+
ev.preventDefault();
|
142
|
+
/* @conditional-compile-remove(mention) */
|
143
|
+
if (mentionSuggestions.length > 0) {
|
144
|
+
const newActiveIndex = activeSuggestionIndex === undefined
|
145
|
+
? 0
|
146
|
+
: Math.min(activeSuggestionIndex + 1, mentionSuggestions.length - 1);
|
147
|
+
setActiveSuggestionIndex(newActiveIndex);
|
148
|
+
}
|
149
|
+
}
|
25
150
|
if (ev.key === 'Enter' && (ev.shiftKey === false || !supportNewline)) {
|
26
151
|
ev.preventDefault();
|
152
|
+
// If we are looking up a mention, select the focused suggestion
|
153
|
+
/* @conditional-compile-remove(mention) */
|
154
|
+
if (mentionSuggestions.length > 0 && activeSuggestionIndex !== undefined) {
|
155
|
+
const selectedMention = mentionSuggestions[activeSuggestionIndex];
|
156
|
+
if (selectedMention) {
|
157
|
+
onSuggestionSelected(selectedMention);
|
158
|
+
return;
|
159
|
+
}
|
160
|
+
}
|
27
161
|
onEnterKeyDown && onEnterKeyDown();
|
28
162
|
}
|
29
163
|
onKeyDown && onKeyDown(ev);
|
30
|
-
}, [
|
164
|
+
}, [
|
165
|
+
onEnterKeyDown,
|
166
|
+
onKeyDown,
|
167
|
+
supportNewline,
|
168
|
+
/* @conditional-compile-remove(mention) */
|
169
|
+
mentionSuggestions,
|
170
|
+
/* @conditional-compile-remove(mention) */
|
171
|
+
activeSuggestionIndex,
|
172
|
+
/* @conditional-compile-remove(mention) */
|
173
|
+
onSuggestionSelected
|
174
|
+
]);
|
175
|
+
/* @conditional-compile-remove(mention) */
|
176
|
+
const debouncedQueryUpdate = useDebouncedCallback((query) => __awaiter(void 0, void 0, void 0, function* () {
|
177
|
+
var _a;
|
178
|
+
const suggestions = (_a = (yield (mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.onQueryUpdated(query)))) !== null && _a !== void 0 ? _a : [];
|
179
|
+
if (suggestions.length === 0) {
|
180
|
+
setActiveSuggestionIndex(undefined);
|
181
|
+
}
|
182
|
+
else if (activeSuggestionIndex === undefined) {
|
183
|
+
setActiveSuggestionIndex(0);
|
184
|
+
}
|
185
|
+
updateMentionSuggestions(suggestions);
|
186
|
+
}), 500);
|
187
|
+
/* @conditional-compile-remove(mention) */
|
188
|
+
useEffect(() => {
|
189
|
+
return () => {
|
190
|
+
debouncedQueryUpdate.cancel();
|
191
|
+
};
|
192
|
+
}, [debouncedQueryUpdate]);
|
193
|
+
/* @conditional-compile-remove(mention) */
|
194
|
+
const handleOnChange = useCallback((event, updatedValue) => __awaiter(void 0, void 0, void 0, function* () {
|
195
|
+
var _b, _c;
|
196
|
+
const newValue = updatedValue !== null && updatedValue !== void 0 ? updatedValue : '';
|
197
|
+
const triggerText = (_b = mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) !== null && _b !== void 0 ? _b : defaultMentionTrigger;
|
198
|
+
const newTextLength = newValue.length;
|
199
|
+
let selectionEnd = ((_c = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _c === void 0 ? void 0 : _c.selectionEnd) || -1;
|
200
|
+
selectionEnd = Math.max(0, selectionEnd);
|
201
|
+
selectionEnd = Math.min(selectionEnd, newTextLength - 1);
|
202
|
+
// If we are enabled for lookups,
|
203
|
+
if (mentionLookupOptions !== undefined) {
|
204
|
+
// Look at the range of the change for a trigger character
|
205
|
+
const triggerPriorIndex = newValue.lastIndexOf(triggerText, selectionEnd - 1);
|
206
|
+
// Update the caret position, if not doing a lookup
|
207
|
+
setCaretPosition(Caret.getRelativePosition(event.currentTarget));
|
208
|
+
if (triggerPriorIndex !== undefined) {
|
209
|
+
// trigger is found
|
210
|
+
const isSpaceBeforeTrigger = newValue.substring(triggerPriorIndex - 1, triggerPriorIndex) === ' ';
|
211
|
+
const wordAtSelection = newValue.substring(triggerPriorIndex, selectionEnd);
|
212
|
+
let tagIndex = currentTriggerStartIndex;
|
213
|
+
if (!isSpaceBeforeTrigger && triggerPriorIndex !== 0) {
|
214
|
+
//no space before the trigger <- continuation of the previous word
|
215
|
+
tagIndex = -1;
|
216
|
+
setCurrentTriggerStartIndex(tagIndex);
|
217
|
+
}
|
218
|
+
else if (wordAtSelection === triggerText) {
|
219
|
+
// start of the mention
|
220
|
+
tagIndex = selectionEnd - triggerText.length;
|
221
|
+
if (tagIndex < 0) {
|
222
|
+
tagIndex = 0;
|
223
|
+
}
|
224
|
+
setCurrentTriggerStartIndex(tagIndex);
|
225
|
+
}
|
226
|
+
if (tagIndex === -1) {
|
227
|
+
updateMentionSuggestions([]);
|
228
|
+
}
|
229
|
+
else {
|
230
|
+
// In the middle of a @mention lookup
|
231
|
+
if (tagIndex > -1) {
|
232
|
+
const query = wordAtSelection.substring(triggerText.length, wordAtSelection.length);
|
233
|
+
if (query !== undefined) {
|
234
|
+
yield debouncedQueryUpdate(query);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
let result = '';
|
241
|
+
if (tagsValue.length === 0) {
|
242
|
+
// no tags in the string, textValue is a sting
|
243
|
+
result = newValue;
|
244
|
+
}
|
245
|
+
else {
|
246
|
+
// there are tags in the text value, textValue is html string
|
247
|
+
const { changeStart, oldChangeEnd, newChangeEnd } = findStringsDiffIndexes(inputTextValue, newValue, selectionEnd);
|
248
|
+
// get updated html string
|
249
|
+
const change = newValue.substring(changeStart, newChangeEnd);
|
250
|
+
const [updatedHTML, updatedChangeNewEndIndex] = updateHTML(textValue, inputTextValue, newValue, tagsValue, changeStart, oldChangeEnd, change, triggerText);
|
251
|
+
result = updatedHTML;
|
252
|
+
if (updatedChangeNewEndIndex !== null) {
|
253
|
+
if ((change.length === 1 && event.currentTarget.selectionStart === event.currentTarget.selectionEnd) || // simple input
|
254
|
+
(change.length === 0 && newChangeEnd === changeStart) //delete
|
255
|
+
) {
|
256
|
+
setCaretIndex(updatedChangeNewEndIndex);
|
257
|
+
}
|
258
|
+
}
|
259
|
+
}
|
260
|
+
onChange && onChange(event, result);
|
261
|
+
}), [
|
262
|
+
onChange,
|
263
|
+
mentionLookupOptions,
|
264
|
+
tagsValue,
|
265
|
+
textValue,
|
266
|
+
inputTextValue,
|
267
|
+
currentTriggerStartIndex,
|
268
|
+
setCaretIndex,
|
269
|
+
setCaretPosition,
|
270
|
+
updateMentionSuggestions,
|
271
|
+
debouncedQueryUpdate,
|
272
|
+
textFieldRef
|
273
|
+
]);
|
274
|
+
/* @conditional-compile-remove(mention) */
|
275
|
+
const updateSelectionIndexesWithMentionIfNeeded = (event) => {
|
276
|
+
var _a;
|
277
|
+
let updatedStartIndex = event.currentTarget.selectionStart;
|
278
|
+
let updatedEndIndex = event.currentTarget.selectionEnd;
|
279
|
+
if (event.currentTarget.selectionStart === event.currentTarget.selectionEnd &&
|
280
|
+
event.currentTarget.selectionStart !== null &&
|
281
|
+
event.currentTarget.selectionStart !== -1) {
|
282
|
+
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionStart);
|
283
|
+
if (mentionTag !== undefined && mentionTag.plainTextBeginIndex !== undefined) {
|
284
|
+
if (selectionStartValue === null) {
|
285
|
+
updatedStartIndex = mentionTag.plainTextBeginIndex;
|
286
|
+
updatedEndIndex = (_a = mentionTag.plainTextEndIndex) !== null && _a !== void 0 ? _a : mentionTag.plainTextBeginIndex;
|
287
|
+
}
|
288
|
+
else {
|
289
|
+
const newSelectionIndex = findNewSelectionIndexForMention(mentionTag, inputTextValue, event.currentTarget.selectionStart, selectionStartValue);
|
290
|
+
updatedStartIndex = newSelectionIndex;
|
291
|
+
updatedEndIndex = newSelectionIndex;
|
292
|
+
}
|
293
|
+
}
|
294
|
+
}
|
295
|
+
else if (event.currentTarget.selectionStart !== event.currentTarget.selectionEnd) {
|
296
|
+
// Both e.currentTarget.selectionStart !== selectionStartValue and e.currentTarget.selectionEnd !== selectionEndValue can be true when a user selects a text by double click
|
297
|
+
if (event.currentTarget.selectionStart !== null && event.currentTarget.selectionStart !== selectionStartValue) {
|
298
|
+
// the selection start is changed
|
299
|
+
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionStart);
|
300
|
+
if (mentionTag !== undefined && mentionTag.plainTextBeginIndex !== undefined) {
|
301
|
+
//TODO: here it takes -1 when it shouldn't, update selectionstart and end with mouse move and or touch move
|
302
|
+
updatedStartIndex = findNewSelectionIndexForMention(mentionTag, inputTextValue, event.currentTarget.selectionStart, selectionStartValue !== null && selectionStartValue !== void 0 ? selectionStartValue : -1);
|
303
|
+
}
|
304
|
+
}
|
305
|
+
if (event.currentTarget.selectionEnd !== null && event.currentTarget.selectionEnd !== selectionEndValue) {
|
306
|
+
// the selection end is changed
|
307
|
+
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionEnd);
|
308
|
+
if (mentionTag !== undefined && mentionTag.plainTextBeginIndex !== undefined) {
|
309
|
+
//TODO: here it takes -1 when it shouldn't, update selectionstart and end with mouse move and or touch move
|
310
|
+
updatedEndIndex = findNewSelectionIndexForMention(mentionTag, inputTextValue, event.currentTarget.selectionEnd, selectionEndValue !== null && selectionEndValue !== void 0 ? selectionEndValue : -1);
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
// e.currentTarget.selectionDirection should be set to handle shift + arrow keys
|
315
|
+
if (event.currentTarget.selectionDirection === null) {
|
316
|
+
event.currentTarget.setSelectionRange(updatedStartIndex, updatedEndIndex);
|
317
|
+
}
|
318
|
+
else {
|
319
|
+
event.currentTarget.setSelectionRange(updatedStartIndex, updatedEndIndex, event.currentTarget.selectionDirection);
|
320
|
+
}
|
321
|
+
setSelectionStartValue(updatedStartIndex);
|
322
|
+
setSelectionEndValue(updatedEndIndex);
|
323
|
+
};
|
324
|
+
const getInputFieldTextValue = () => {
|
325
|
+
/* @conditional-compile-remove(mention) */
|
326
|
+
return inputTextValue;
|
327
|
+
return textValue;
|
328
|
+
};
|
31
329
|
return (React.createElement(Stack, { className: mergedRootStyle },
|
32
330
|
React.createElement("div", { className: mergedTextContainerStyle },
|
33
|
-
|
331
|
+
/* @conditional-compile-remove(mention) */ mentionSuggestions.length > 0 && (React.createElement(_MentionPopover, { suggestions: mentionSuggestions, activeSuggestionIndex: activeSuggestionIndex, target: inputBoxRef, targetPositionOffset: caretPosition, onRenderSuggestionItem: mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.onRenderSuggestionItem, onSuggestionSelected: onSuggestionSelected, onDismiss: () => {
|
332
|
+
updateMentionSuggestions([]);
|
333
|
+
} })),
|
334
|
+
React.createElement(TextField, { autoFocus: props.autoFocus === 'sendBoxTextField', "data-ui-id": dataUiId, multiline: true, autoAdjustHeight: true, multiple: false, resizable: false, componentRef: textFieldRef, id: id, inputClassName: mergedTextFiledStyle, placeholder: placeholderText, value: getInputFieldTextValue(), onChange: (e, newValue) => {
|
335
|
+
/* @conditional-compile-remove(mention) */
|
336
|
+
setInputTextValue(newValue !== null && newValue !== void 0 ? newValue : '');
|
337
|
+
/* @conditional-compile-remove(mention) */
|
338
|
+
handleOnChange(e, newValue);
|
339
|
+
/* @conditional-compile-remove(mention) */
|
340
|
+
return;
|
341
|
+
onChange(e, newValue);
|
342
|
+
},
|
343
|
+
/* @conditional-compile-remove(mention) */
|
344
|
+
onSelect: (e) => {
|
345
|
+
var _a, _b, _c;
|
346
|
+
if (caretIndex !== undefined) {
|
347
|
+
e.currentTarget.setSelectionRange(caretIndex, caretIndex);
|
348
|
+
setCaretIndex(undefined);
|
349
|
+
return;
|
350
|
+
}
|
351
|
+
//TODO: need to check to navigate before/after space correctly in tag + when selecting by mouse
|
352
|
+
/* @conditional-compile-remove(mention) */
|
353
|
+
if (shouldHandleOnMouseDownDuringSelect &&
|
354
|
+
e.currentTarget.selectionStart !== null &&
|
355
|
+
e.currentTarget.selectionStart === e.currentTarget.selectionEnd) {
|
356
|
+
// handle mention click
|
357
|
+
const mentionTag = findMentionTagForSelection(tagsValue, e.currentTarget.selectionStart);
|
358
|
+
if (mentionTag !== undefined && mentionTag.plainTextBeginIndex !== undefined) {
|
359
|
+
if (e.currentTarget.selectionDirection === null) {
|
360
|
+
e.currentTarget.setSelectionRange(mentionTag.plainTextBeginIndex, (_a = mentionTag.plainTextEndIndex) !== null && _a !== void 0 ? _a : mentionTag.plainTextBeginIndex);
|
361
|
+
}
|
362
|
+
else {
|
363
|
+
e.currentTarget.setSelectionRange(mentionTag.plainTextBeginIndex, (_b = mentionTag.plainTextEndIndex) !== null && _b !== void 0 ? _b : mentionTag.plainTextBeginIndex, e.currentTarget.selectionDirection);
|
364
|
+
}
|
365
|
+
setSelectionStartValue(mentionTag.plainTextBeginIndex);
|
366
|
+
setSelectionEndValue((_c = mentionTag.plainTextEndIndex) !== null && _c !== void 0 ? _c : mentionTag.plainTextBeginIndex);
|
367
|
+
}
|
368
|
+
else {
|
369
|
+
setSelectionStartValue(e.currentTarget.selectionStart);
|
370
|
+
setSelectionEndValue(e.currentTarget.selectionEnd);
|
371
|
+
}
|
372
|
+
}
|
373
|
+
else {
|
374
|
+
updateSelectionIndexesWithMentionIfNeeded(e);
|
375
|
+
}
|
376
|
+
/* @conditional-compile-remove(mention) */
|
377
|
+
setShouldHandleOnMouseDownDuringSelect(false);
|
378
|
+
}, onMouseDown: () => {
|
379
|
+
// as events order is onMouseDown -> onSelect -> onClick
|
380
|
+
// onClick and onMouseDown can't handle clicking on mention event because
|
381
|
+
// onClick has wrong range as it's called after onSelect
|
382
|
+
// onMouseDown doesn't have correct selectionRange yet
|
383
|
+
// so we need to handle onMouseDown to prevent onSelect default behavior
|
384
|
+
/* @conditional-compile-remove(mention) */
|
385
|
+
setShouldHandleOnMouseDownDuringSelect(true);
|
386
|
+
}, onTouchStart: () => {
|
387
|
+
// see onMouseDown for more details
|
388
|
+
/* @conditional-compile-remove(mention) */
|
389
|
+
setShouldHandleOnMouseDownDuringSelect(true);
|
390
|
+
}, autoComplete: "off", onKeyDown: onTextFieldKeyDown, styles: mergedTextFieldStyle, disabled: disabled, errorMessage: errorMessage, elementRef: inputBoxRef }),
|
34
391
|
React.createElement(Stack, { horizontal: true, className: mergeStyles(props.inlineChildren ? inlineButtonsContainerStyle : newLineButtonsContainerStyle) }, children))));
|
35
392
|
};
|
36
393
|
/**
|
@@ -55,4 +412,680 @@ export const InputBoxButton = (props) => {
|
|
55
412
|
setIsHover(false);
|
56
413
|
}, onRenderIcon: () => onRenderIcon(isHover) })));
|
57
414
|
};
|
415
|
+
/* @conditional-compile-remove(mention) */
|
416
|
+
/**
|
417
|
+
* Find mention tag if selection is inside of it
|
418
|
+
*
|
419
|
+
* @private
|
420
|
+
*/
|
421
|
+
const findMentionTagForSelection = (tags, selection) => {
|
422
|
+
let mentionTag = undefined;
|
423
|
+
for (let i = 0; i < tags.length; i++) {
|
424
|
+
const tag = tags[i];
|
425
|
+
let plainTextEndIndex = 0;
|
426
|
+
if (tag.plainTextEndIndex !== undefined && tag.closeTagIdx !== undefined) {
|
427
|
+
// close tag exists
|
428
|
+
plainTextEndIndex = tag.plainTextEndIndex;
|
429
|
+
}
|
430
|
+
else if (tag.plainTextBeginIndex !== undefined) {
|
431
|
+
//no close tag
|
432
|
+
plainTextEndIndex = tag.plainTextBeginIndex;
|
433
|
+
}
|
434
|
+
if (tag.subTags !== undefined && tag.subTags.length !== 0) {
|
435
|
+
const selectedTag = findMentionTagForSelection(tag.subTags, selection);
|
436
|
+
if (selectedTag !== undefined) {
|
437
|
+
mentionTag = selectedTag;
|
438
|
+
break;
|
439
|
+
}
|
440
|
+
}
|
441
|
+
else if (tag.tagType === 'msft-mention' &&
|
442
|
+
tag.plainTextBeginIndex !== undefined &&
|
443
|
+
tag.plainTextBeginIndex < selection &&
|
444
|
+
selection < plainTextEndIndex) {
|
445
|
+
mentionTag = tag;
|
446
|
+
break;
|
447
|
+
}
|
448
|
+
}
|
449
|
+
return mentionTag;
|
450
|
+
};
|
451
|
+
/* @conditional-compile-remove(mention) */
|
452
|
+
/**
|
453
|
+
* Go through tags and find a new the selection index if it is inside of a mention tag
|
454
|
+
*
|
455
|
+
* @private
|
456
|
+
*/
|
457
|
+
const findNewSelectionIndexForMention = (tag, textValue, selection, previousSelection) => {
|
458
|
+
var _a;
|
459
|
+
if (tag.plainTextBeginIndex === undefined ||
|
460
|
+
tag.tagType !== 'msft-mention' ||
|
461
|
+
selection === previousSelection ||
|
462
|
+
tag.plainTextEndIndex === undefined) {
|
463
|
+
return selection;
|
464
|
+
}
|
465
|
+
let spaceIndex = 0;
|
466
|
+
if (selection <= previousSelection) {
|
467
|
+
// the cursor is moved to the left
|
468
|
+
spaceIndex = textValue.lastIndexOf(' ', selection !== null && selection !== void 0 ? selection : 0);
|
469
|
+
if (spaceIndex === -1) {
|
470
|
+
// no space before the selection
|
471
|
+
spaceIndex = tag.plainTextBeginIndex;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
else {
|
475
|
+
// the cursor is moved to the right
|
476
|
+
spaceIndex = textValue.indexOf(' ', selection !== null && selection !== void 0 ? selection : 0);
|
477
|
+
if (spaceIndex === -1) {
|
478
|
+
// no space after the selection
|
479
|
+
spaceIndex = (_a = tag.plainTextEndIndex) !== null && _a !== void 0 ? _a : tag.plainTextBeginIndex;
|
480
|
+
}
|
481
|
+
}
|
482
|
+
if (spaceIndex < tag.plainTextBeginIndex) {
|
483
|
+
spaceIndex = tag.plainTextBeginIndex;
|
484
|
+
}
|
485
|
+
else if (spaceIndex > tag.plainTextEndIndex) {
|
486
|
+
spaceIndex = tag.plainTextEndIndex;
|
487
|
+
}
|
488
|
+
return spaceIndex;
|
489
|
+
};
|
490
|
+
/* @conditional-compile-remove(mention) */
|
491
|
+
/**
|
492
|
+
* Handle mention tag edit and by word deleting
|
493
|
+
*
|
494
|
+
* @private
|
495
|
+
*/
|
496
|
+
const handleMentionTagUpdate = (htmlText, oldPlainText, lastProcessedHTMLIndex, processedChange, tag, closeTagIdx, closeTagLength, plainTextEndIndex, startIndex, oldPlainTextEndIndex, mentionTagLength) => {
|
497
|
+
if (tag.tagType !== 'msft-mention' || tag.plainTextBeginIndex === undefined) {
|
498
|
+
return ['', processedChange, lastProcessedHTMLIndex, null];
|
499
|
+
}
|
500
|
+
let result = '';
|
501
|
+
let plainTextSelectionEndIndex = null;
|
502
|
+
let rangeStart;
|
503
|
+
let rangeEnd;
|
504
|
+
// check if space symbol is handled in case if string looks like '<1 2 3>'
|
505
|
+
let isSpaceLengthHandled = false;
|
506
|
+
rangeStart = oldPlainText.lastIndexOf(' ', startIndex);
|
507
|
+
if (rangeStart !== -1 && rangeStart !== undefined && rangeStart > tag.plainTextBeginIndex) {
|
508
|
+
isSpaceLengthHandled = true;
|
509
|
+
}
|
510
|
+
rangeEnd = oldPlainText.indexOf(' ', oldPlainTextEndIndex);
|
511
|
+
if (rangeEnd === -1 || rangeEnd === undefined) {
|
512
|
+
// check if space symbol is not found
|
513
|
+
rangeEnd = plainTextEndIndex;
|
514
|
+
}
|
515
|
+
else if (!isSpaceLengthHandled) {
|
516
|
+
// +1 to include the space symbol
|
517
|
+
rangeEnd += 1;
|
518
|
+
}
|
519
|
+
isSpaceLengthHandled = true;
|
520
|
+
if (rangeStart === -1 || rangeStart === undefined || rangeStart < tag.plainTextBeginIndex) {
|
521
|
+
rangeStart = tag.plainTextBeginIndex;
|
522
|
+
}
|
523
|
+
if (rangeEnd > plainTextEndIndex) {
|
524
|
+
rangeEnd = plainTextEndIndex;
|
525
|
+
}
|
526
|
+
if (rangeStart === tag.plainTextBeginIndex && rangeEnd === plainTextEndIndex) {
|
527
|
+
// the whole tag should be removed
|
528
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx) + processedChange;
|
529
|
+
plainTextSelectionEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
530
|
+
processedChange = '';
|
531
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
532
|
+
}
|
533
|
+
else {
|
534
|
+
// only part of the tag should be removed
|
535
|
+
let startChangeDiff = 0;
|
536
|
+
let endChangeDiff = 0;
|
537
|
+
// need to check only rangeStart > tag.plainTextBeginIndex as when rangeStart === tag.plainTextBeginIndex startChangeDiff = 0 and mentionTagLength shouldn't be subtracted
|
538
|
+
if (rangeStart > tag.plainTextBeginIndex) {
|
539
|
+
startChangeDiff = rangeStart - tag.plainTextBeginIndex - mentionTagLength;
|
540
|
+
}
|
541
|
+
endChangeDiff = rangeEnd - tag.plainTextBeginIndex - mentionTagLength;
|
542
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length + startChangeDiff);
|
543
|
+
// plainTextSelectionEndIndex = rangeStart + processedChange.length;
|
544
|
+
lastProcessedHTMLIndex = tag.openTagIdx + tag.openTagBody.length + endChangeDiff;
|
545
|
+
// processed change should not be changed as it should be added after the tag
|
546
|
+
}
|
547
|
+
return [result, processedChange, lastProcessedHTMLIndex, plainTextSelectionEndIndex];
|
548
|
+
};
|
549
|
+
/* @conditional-compile-remove(mention) */
|
550
|
+
/**
|
551
|
+
* Go through the text and update it with the changed text
|
552
|
+
*
|
553
|
+
* @private
|
554
|
+
*/
|
555
|
+
const updateHTML = (htmlText, oldPlainText, newPlainText, tags, startIndex, oldPlainTextEndIndex, change, mentionTrigger) => {
|
556
|
+
let result = '';
|
557
|
+
if (tags.length === 0) {
|
558
|
+
// no tags added yet
|
559
|
+
return [newPlainText, null];
|
560
|
+
}
|
561
|
+
if (startIndex === 0 && oldPlainTextEndIndex === oldPlainText.length) {
|
562
|
+
// the whole text is changed
|
563
|
+
return [newPlainText, null];
|
564
|
+
}
|
565
|
+
let lastProcessedHTMLIndex = 0;
|
566
|
+
// the value can be updated with empty string when the change covers more than 1 place (tag + before or after the tag)
|
567
|
+
// in this case change won't be added as part of the tag
|
568
|
+
// e.g.: change is before and partially in tag => change will be added before the tag and outdated text in the tag will be removed
|
569
|
+
// e.g.: change is after and partially in tag => change will be added after the tag and outdated text in the tag will be removed
|
570
|
+
// e.g.: change is on the beginning of the tag => change will be added before the tag
|
571
|
+
// e.g.: change is on the end of the tag => change will be added to the tag if it's not mention and after the tag if it's mention
|
572
|
+
let processedChange = change;
|
573
|
+
// end tag plain text index of the last processed tag
|
574
|
+
let lastProcessedPlainTextTagEndIndex = 0;
|
575
|
+
// as some tags/text can be removed fully, selectionEnd should be updated correctly
|
576
|
+
let changeNewEndIndex = null;
|
577
|
+
for (let i = 0; i < tags.length; i++) {
|
578
|
+
const tag = tags[i];
|
579
|
+
if (tag.plainTextBeginIndex === undefined) {
|
580
|
+
continue;
|
581
|
+
}
|
582
|
+
// all plain text indexes includes trigger length for the mention that shouldn't be included in
|
583
|
+
// htmlText.substring because html strings don't include the trigger
|
584
|
+
// mentionTagLength will be set only for 'msft-mention', otherwise should be 0
|
585
|
+
let mentionTagLength = 0;
|
586
|
+
let isMentionTag = false;
|
587
|
+
if (tag.tagType === 'msft-mention') {
|
588
|
+
mentionTagLength = mentionTrigger.length;
|
589
|
+
isMentionTag = true;
|
590
|
+
}
|
591
|
+
//change start is before the open tag
|
592
|
+
if (startIndex <= tag.plainTextBeginIndex) {
|
593
|
+
// Math.max(lastProcessedPlainTextTagEndIndex, startIndex) is used as startIndex may not be in [[previous tag].plainTextEndIndex - tag.plainTextBeginIndex] range
|
594
|
+
const startChangeDiff = tag.plainTextBeginIndex - Math.max(lastProcessedPlainTextTagEndIndex, startIndex);
|
595
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx - startChangeDiff) + processedChange;
|
596
|
+
if (oldPlainTextEndIndex <= tag.plainTextBeginIndex) {
|
597
|
+
// the whole change is before tag start
|
598
|
+
// oldPlainTextEndIndex already includes mentionTag length
|
599
|
+
const endChangeDiff = tag.plainTextBeginIndex - oldPlainTextEndIndex;
|
600
|
+
lastProcessedHTMLIndex = tag.openTagIdx - endChangeDiff;
|
601
|
+
processedChange = '';
|
602
|
+
// the change is handled; exit
|
603
|
+
break;
|
604
|
+
}
|
605
|
+
else {
|
606
|
+
// change continues in the tag
|
607
|
+
lastProcessedHTMLIndex = tag.openTagIdx;
|
608
|
+
processedChange = '';
|
609
|
+
// proceed to the next check
|
610
|
+
}
|
611
|
+
}
|
612
|
+
let plainTextEndIndex = 0;
|
613
|
+
let closeTagIdx = 0;
|
614
|
+
let closeTagLength = 0;
|
615
|
+
if (tag.plainTextEndIndex !== undefined && tag.closeTagIdx !== undefined) {
|
616
|
+
// close tag exists
|
617
|
+
plainTextEndIndex = tag.plainTextEndIndex;
|
618
|
+
closeTagIdx = tag.closeTagIdx;
|
619
|
+
// tag.tagType.length + </>
|
620
|
+
closeTagLength = tag.tagType.length + 3;
|
621
|
+
}
|
622
|
+
else {
|
623
|
+
// no close tag
|
624
|
+
plainTextEndIndex = tag.plainTextBeginIndex;
|
625
|
+
closeTagIdx = tag.openTagIdx + tag.openTagBody.length;
|
626
|
+
closeTagLength = 0;
|
627
|
+
}
|
628
|
+
if (startIndex < plainTextEndIndex) {
|
629
|
+
// change started before the end tag
|
630
|
+
if (startIndex <= tag.plainTextBeginIndex && oldPlainTextEndIndex === plainTextEndIndex) {
|
631
|
+
// the change is a tag or starts before the tag
|
632
|
+
// tag should be removed, no matter if there are subtags
|
633
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx) + processedChange;
|
634
|
+
processedChange = '';
|
635
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
636
|
+
// the change is handled; exit
|
637
|
+
break;
|
638
|
+
}
|
639
|
+
else if (startIndex >= tag.plainTextBeginIndex && oldPlainTextEndIndex < plainTextEndIndex) {
|
640
|
+
// edge case: the change is between tag
|
641
|
+
if (isMentionTag) {
|
642
|
+
if (change !== '') {
|
643
|
+
// mention tag should be deleted when user tries to edit it
|
644
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx) + processedChange;
|
645
|
+
changeNewEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
646
|
+
processedChange = '';
|
647
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
648
|
+
}
|
649
|
+
else {
|
650
|
+
const [resultValue, updatedChange, htmlIndex, plainTextSelectionEndIndex] = handleMentionTagUpdate(htmlText, oldPlainText, lastProcessedHTMLIndex, processedChange, tag, closeTagIdx, closeTagLength, plainTextEndIndex, startIndex, oldPlainTextEndIndex, mentionTagLength);
|
651
|
+
result += resultValue;
|
652
|
+
changeNewEndIndex = plainTextSelectionEndIndex;
|
653
|
+
processedChange = updatedChange;
|
654
|
+
lastProcessedHTMLIndex = htmlIndex;
|
655
|
+
}
|
656
|
+
// the change is handled; exit
|
657
|
+
break;
|
658
|
+
}
|
659
|
+
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content) {
|
660
|
+
// with subtags
|
661
|
+
// before the tag content
|
662
|
+
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length);
|
663
|
+
lastProcessedHTMLIndex = closeTagIdx;
|
664
|
+
const [content, updatedChangeNewEndIndex] = updateHTML(tag.content, oldPlainText, newPlainText, tag.subTags, startIndex - mentionTagLength, oldPlainTextEndIndex - mentionTagLength, processedChange, mentionTrigger);
|
665
|
+
result += stringBefore + content;
|
666
|
+
changeNewEndIndex = updatedChangeNewEndIndex;
|
667
|
+
break;
|
668
|
+
}
|
669
|
+
else {
|
670
|
+
// no subtags
|
671
|
+
const startChangeDiff = startIndex - tag.plainTextBeginIndex - mentionTagLength;
|
672
|
+
const endChangeDiff = oldPlainTextEndIndex - tag.plainTextBeginIndex - mentionTagLength;
|
673
|
+
result +=
|
674
|
+
htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length + startChangeDiff) +
|
675
|
+
processedChange;
|
676
|
+
processedChange = '';
|
677
|
+
lastProcessedHTMLIndex = tag.openTagIdx + tag.openTagBody.length + endChangeDiff;
|
678
|
+
// the change is handled; exit
|
679
|
+
break;
|
680
|
+
}
|
681
|
+
}
|
682
|
+
else if (startIndex > tag.plainTextBeginIndex && oldPlainTextEndIndex > plainTextEndIndex) {
|
683
|
+
//the change started in the tag but finishes somewhere further
|
684
|
+
const startChangeDiff = startIndex - tag.plainTextBeginIndex - mentionTagLength;
|
685
|
+
if (isMentionTag) {
|
686
|
+
const [resultValue, updatedChange, htmlIndex] = handleMentionTagUpdate(htmlText, oldPlainText, lastProcessedHTMLIndex, oldPlainText.substring(startIndex, startIndex + 1) !== ' ' && change === '' ? ' ' : '', // if substring !== ' ' && change is empty -> the change should be " " and not empty string but " " wasn't included in change; otherwise the part of mention should be just deleted without processedChange update
|
687
|
+
tag, closeTagIdx, closeTagLength, plainTextEndIndex, startIndex, oldPlainTextEndIndex, mentionTagLength);
|
688
|
+
result += resultValue;
|
689
|
+
lastProcessedHTMLIndex = htmlIndex;
|
690
|
+
processedChange = updatedChange;
|
691
|
+
// no need to handle plainTextSelectionEndIndex as the change will be added later
|
692
|
+
// proceed with the next calculations
|
693
|
+
}
|
694
|
+
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
695
|
+
// with subtags
|
696
|
+
// before the tag content
|
697
|
+
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length);
|
698
|
+
lastProcessedHTMLIndex = closeTagIdx;
|
699
|
+
const [content] = updateHTML(tag.content, oldPlainText, newPlainText, tag.subTags, startIndex - mentionTagLength, oldPlainTextEndIndex - mentionTagLength, '', // the part of the tag should be just deleted without processedChange update and change will be added after this tag
|
700
|
+
mentionTrigger);
|
701
|
+
result += stringBefore + content;
|
702
|
+
// proceed with the next calculations
|
703
|
+
}
|
704
|
+
else {
|
705
|
+
// no subtags
|
706
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length + startChangeDiff);
|
707
|
+
lastProcessedHTMLIndex = closeTagIdx;
|
708
|
+
// proceed with the next calculations
|
709
|
+
}
|
710
|
+
}
|
711
|
+
else if (startIndex < tag.plainTextBeginIndex && oldPlainTextEndIndex > plainTextEndIndex) {
|
712
|
+
// the change starts before the tag and finishes after it
|
713
|
+
// tag should be removed, no matter if there are subtags
|
714
|
+
// no need to save anything between lastProcessedHTMLIndex and closeTagIdx + closeTagLength
|
715
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
716
|
+
// proceed with the next calculations
|
717
|
+
}
|
718
|
+
else if (startIndex === tag.plainTextBeginIndex && oldPlainTextEndIndex > plainTextEndIndex) {
|
719
|
+
// the change starts in the tag and finishes after it
|
720
|
+
// tag should be removed, no matter if there are subtags
|
721
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx);
|
722
|
+
// processedChange shouldn't be updated as it will be added after the tag
|
723
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
724
|
+
// proceed with the next calculations
|
725
|
+
}
|
726
|
+
else if (startIndex < tag.plainTextBeginIndex && oldPlainTextEndIndex < plainTextEndIndex) {
|
727
|
+
// the change starts before the tag and ends in a tag
|
728
|
+
if (isMentionTag) {
|
729
|
+
const [resultValue, , htmlIndex] = handleMentionTagUpdate(htmlText, oldPlainText, lastProcessedHTMLIndex, '', // the part of mention should be just deleted without processedChange update
|
730
|
+
tag, closeTagIdx, closeTagLength, plainTextEndIndex, startIndex, oldPlainTextEndIndex, mentionTagLength);
|
731
|
+
changeNewEndIndex = tag.plainTextBeginIndex;
|
732
|
+
result += resultValue;
|
733
|
+
lastProcessedHTMLIndex = htmlIndex;
|
734
|
+
}
|
735
|
+
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
736
|
+
// with subtags
|
737
|
+
// before the tag content
|
738
|
+
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length);
|
739
|
+
lastProcessedHTMLIndex = closeTagIdx;
|
740
|
+
const [content] = updateHTML(tag.content, oldPlainText, newPlainText, tag.subTags, startIndex - mentionTagLength, oldPlainTextEndIndex - mentionTagLength, processedChange, // processedChange should equal '' and the part of the tag should be deleted as the change was handled before this tag
|
741
|
+
mentionTrigger);
|
742
|
+
result += stringBefore + content;
|
743
|
+
}
|
744
|
+
else {
|
745
|
+
// no subtags
|
746
|
+
result +=
|
747
|
+
htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length) + processedChange;
|
748
|
+
processedChange = '';
|
749
|
+
// oldPlainTextEndIndex already includes mentionTag length
|
750
|
+
const endChangeDiff = plainTextEndIndex - oldPlainTextEndIndex;
|
751
|
+
// as change may be before the end of the tag, we need to add the rest of the tag
|
752
|
+
lastProcessedHTMLIndex = closeTagIdx - endChangeDiff;
|
753
|
+
}
|
754
|
+
// the change is handled; exit
|
755
|
+
break;
|
756
|
+
}
|
757
|
+
else if (startIndex > tag.plainTextBeginIndex && oldPlainTextEndIndex === plainTextEndIndex) {
|
758
|
+
// the change starts in the tag and ends at the end of a tag
|
759
|
+
if (isMentionTag) {
|
760
|
+
if (change !== '' && startIndex === plainTextEndIndex) {
|
761
|
+
// non empty change at the end of the mention tag to be added after the mention tag
|
762
|
+
result += htmlText.substring(lastProcessedHTMLIndex, closeTagIdx + closeTagLength) + processedChange;
|
763
|
+
changeNewEndIndex = plainTextEndIndex + processedChange.length;
|
764
|
+
processedChange = '';
|
765
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
766
|
+
}
|
767
|
+
else if (change !== '') {
|
768
|
+
// mention tag should be deleted when user tries to edit it
|
769
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx) + processedChange;
|
770
|
+
changeNewEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
771
|
+
processedChange = '';
|
772
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
773
|
+
}
|
774
|
+
else {
|
775
|
+
const [resultValue, updatedChange, htmlIndex, plainTextSelectionEndIndex] = handleMentionTagUpdate(htmlText, oldPlainText, lastProcessedHTMLIndex, processedChange, tag, closeTagIdx, closeTagLength, plainTextEndIndex, startIndex, oldPlainTextEndIndex, mentionTagLength);
|
776
|
+
result += resultValue;
|
777
|
+
processedChange = updatedChange;
|
778
|
+
lastProcessedHTMLIndex = htmlIndex;
|
779
|
+
changeNewEndIndex = plainTextSelectionEndIndex;
|
780
|
+
}
|
781
|
+
// the change is handled; exit
|
782
|
+
break;
|
783
|
+
}
|
784
|
+
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
785
|
+
// with subtags
|
786
|
+
// before the tag content
|
787
|
+
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length);
|
788
|
+
lastProcessedHTMLIndex = closeTagIdx;
|
789
|
+
const [content, updatedChangeNewEndIndex] = updateHTML(tag.content, oldPlainText, newPlainText, tag.subTags, startIndex - mentionTagLength, oldPlainTextEndIndex - mentionTagLength, processedChange, mentionTrigger);
|
790
|
+
result += stringBefore + content;
|
791
|
+
changeNewEndIndex = updatedChangeNewEndIndex;
|
792
|
+
break;
|
793
|
+
}
|
794
|
+
else {
|
795
|
+
// no subtags
|
796
|
+
const startChangeDiff = startIndex - tag.plainTextBeginIndex - mentionTagLength;
|
797
|
+
result +=
|
798
|
+
htmlText.substring(lastProcessedHTMLIndex, tag.openTagIdx + tag.openTagBody.length + startChangeDiff) +
|
799
|
+
processedChange;
|
800
|
+
processedChange = '';
|
801
|
+
lastProcessedHTMLIndex = closeTagIdx;
|
802
|
+
// the change is handled; exit
|
803
|
+
break;
|
804
|
+
}
|
805
|
+
}
|
806
|
+
lastProcessedPlainTextTagEndIndex = plainTextEndIndex;
|
807
|
+
}
|
808
|
+
if (i === tags.length - 1 && oldPlainTextEndIndex >= plainTextEndIndex) {
|
809
|
+
// the last tag should handle the end of the change if needed
|
810
|
+
// oldPlainTextEndIndex already includes mentionTag length
|
811
|
+
const endChangeDiff = oldPlainTextEndIndex - plainTextEndIndex;
|
812
|
+
if (startIndex >= plainTextEndIndex) {
|
813
|
+
const startChangeDiff = startIndex - plainTextEndIndex;
|
814
|
+
result +=
|
815
|
+
htmlText.substring(lastProcessedHTMLIndex, closeTagIdx + closeTagLength + startChangeDiff) + processedChange;
|
816
|
+
}
|
817
|
+
else {
|
818
|
+
result += htmlText.substring(lastProcessedHTMLIndex, closeTagIdx + closeTagLength) + processedChange;
|
819
|
+
}
|
820
|
+
processedChange = '';
|
821
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength + endChangeDiff;
|
822
|
+
// the change is handled; exit
|
823
|
+
// break is not required here as this is the last element but added for consistency
|
824
|
+
break;
|
825
|
+
}
|
826
|
+
}
|
827
|
+
if (lastProcessedHTMLIndex < htmlText.length) {
|
828
|
+
result += htmlText.substring(lastProcessedHTMLIndex);
|
829
|
+
}
|
830
|
+
return [result, changeNewEndIndex];
|
831
|
+
};
|
832
|
+
/* @conditional-compile-remove(mention) */
|
833
|
+
/**
|
834
|
+
* Given the oldText and newText, find the start index, old end index and new end index for the changes
|
835
|
+
*
|
836
|
+
* @param oldText - the old text
|
837
|
+
* @param newText - the new text
|
838
|
+
* @param selectionEnd - the end of the selection
|
839
|
+
* @returns change start index, old end index and new end index. The old and new end indexes are exclusive.
|
840
|
+
* @private
|
841
|
+
*/
|
842
|
+
const findStringsDiffIndexes = (oldText, newText, selectionEnd // should be a valid position in the input field
|
843
|
+
) => {
|
844
|
+
const newTextLength = newText.length;
|
845
|
+
const oldTextLength = oldText.length;
|
846
|
+
let changeStart = 0;
|
847
|
+
let newChangeEnd = newTextLength;
|
848
|
+
let oldChangeEnd = oldTextLength;
|
849
|
+
const length = Math.min(newTextLength, oldTextLength, selectionEnd);
|
850
|
+
for (let i = 0; i < length; i++) {
|
851
|
+
if (newText[i] !== oldText[i]) {
|
852
|
+
// the symbol with changeStart index is updated
|
853
|
+
changeStart = i;
|
854
|
+
break;
|
855
|
+
}
|
856
|
+
else if (i === length - 1 && newText[i] === oldText[i]) {
|
857
|
+
// the symbol is added at the end of inputTextValue
|
858
|
+
changeStart = length;
|
859
|
+
break;
|
860
|
+
}
|
861
|
+
}
|
862
|
+
if (oldTextLength < newTextLength) {
|
863
|
+
//insert or replacement
|
864
|
+
if (oldTextLength === changeStart) {
|
865
|
+
// when change was at the end of string
|
866
|
+
// Change is found
|
867
|
+
newChangeEnd = newTextLength;
|
868
|
+
oldChangeEnd = oldTextLength;
|
869
|
+
}
|
870
|
+
else {
|
871
|
+
for (let i = 1; i < newTextLength && oldTextLength - i >= changeStart; i++) {
|
872
|
+
newChangeEnd = newTextLength - i - 1;
|
873
|
+
oldChangeEnd = oldTextLength - i - 1;
|
874
|
+
if (newText[newChangeEnd] !== oldText[oldChangeEnd]) {
|
875
|
+
// Change is found
|
876
|
+
break;
|
877
|
+
}
|
878
|
+
}
|
879
|
+
// make indexes exclusive
|
880
|
+
newChangeEnd += 1;
|
881
|
+
oldChangeEnd += 1;
|
882
|
+
}
|
883
|
+
}
|
884
|
+
else if (oldTextLength > newTextLength) {
|
885
|
+
//deletion or replacement
|
886
|
+
if (newTextLength === changeStart) {
|
887
|
+
// when change was at the end of string
|
888
|
+
// Change is found
|
889
|
+
newChangeEnd = newTextLength;
|
890
|
+
oldChangeEnd = oldTextLength;
|
891
|
+
}
|
892
|
+
else {
|
893
|
+
for (let i = 1; i < oldTextLength && newTextLength - i >= changeStart; i++) {
|
894
|
+
newChangeEnd = newTextLength - i - 1;
|
895
|
+
oldChangeEnd = oldTextLength - i - 1;
|
896
|
+
if (newText[newChangeEnd] !== oldText[oldChangeEnd]) {
|
897
|
+
// Change is found
|
898
|
+
break;
|
899
|
+
}
|
900
|
+
}
|
901
|
+
// make indexes exclusive
|
902
|
+
newChangeEnd += 1;
|
903
|
+
oldChangeEnd += 1;
|
904
|
+
}
|
905
|
+
}
|
906
|
+
else {
|
907
|
+
//replacement
|
908
|
+
for (let i = 1; i < oldTextLength && oldTextLength - i >= changeStart; i++) {
|
909
|
+
newChangeEnd = newTextLength - i - 1;
|
910
|
+
oldChangeEnd = oldTextLength - i - 1;
|
911
|
+
if (newText[newChangeEnd] !== oldText[oldChangeEnd]) {
|
912
|
+
// Change is found
|
913
|
+
break;
|
914
|
+
}
|
915
|
+
}
|
916
|
+
// make indexes exclusive if they aren't equal to the length of the string
|
917
|
+
if (newChangeEnd !== newText.length) {
|
918
|
+
newChangeEnd += 1;
|
919
|
+
}
|
920
|
+
if (oldChangeEnd !== oldText.length) {
|
921
|
+
oldChangeEnd += 1;
|
922
|
+
}
|
923
|
+
}
|
924
|
+
return { changeStart, oldChangeEnd, newChangeEnd };
|
925
|
+
};
|
926
|
+
/* @conditional-compile-remove(mention) */
|
927
|
+
const htmlStringForMentionSuggestion = (suggestion, localeStrings) => {
|
928
|
+
const idHTML = ' id ="' + suggestion.id + '"';
|
929
|
+
const displayTextHTML = ' displayText ="' + suggestion.displayText + '"';
|
930
|
+
const displayText = getDisplayNameForMentionSuggestion(suggestion, localeStrings);
|
931
|
+
return '<msft-mention' + idHTML + displayTextHTML + '>' + displayText + '</msft-mention>';
|
932
|
+
};
|
933
|
+
/* @conditional-compile-remove(mention) */
|
934
|
+
const getDisplayNameForMentionSuggestion = (suggestion, localeStrings) => {
|
935
|
+
const displayNamePlaceholder = localeStrings.participantItem.displayNamePlaceholder;
|
936
|
+
return suggestion.displayText !== '' ? suggestion.displayText : displayNamePlaceholder !== null && displayNamePlaceholder !== void 0 ? displayNamePlaceholder : '';
|
937
|
+
};
|
938
|
+
/* @conditional-compile-remove(mention) */
|
939
|
+
/**
|
940
|
+
* Parse the text and return the tags and the plain text in one go
|
941
|
+
* @param text - The text to parse for HTML tags
|
942
|
+
* @param trigger The trigger to show for the msft-mention tag in plain text
|
943
|
+
*
|
944
|
+
* @returns An array of tags and the plain text representation
|
945
|
+
*/
|
946
|
+
const textToTagParser = (text, trigger) => {
|
947
|
+
var _a, _b;
|
948
|
+
const tags = []; // Tags passed back to the caller
|
949
|
+
const tagParseStack = []; // Local stack to use while parsing
|
950
|
+
let plainTextRepresentation = '';
|
951
|
+
let parseIndex = 0;
|
952
|
+
while (parseIndex < text.length) {
|
953
|
+
const foundHtmlTag = findNextHtmlTag(text, parseIndex);
|
954
|
+
if (!foundHtmlTag) {
|
955
|
+
if (parseIndex !== 0) {
|
956
|
+
// Add the remaining text to the plain text representation
|
957
|
+
plainTextRepresentation += text.substring(parseIndex);
|
958
|
+
}
|
959
|
+
else {
|
960
|
+
plainTextRepresentation = text;
|
961
|
+
}
|
962
|
+
break;
|
963
|
+
}
|
964
|
+
if (foundHtmlTag.type === 'open' || foundHtmlTag.type === 'self-closing') {
|
965
|
+
const nextTag = parseOpenTag(foundHtmlTag.content, foundHtmlTag.startIdx);
|
966
|
+
// Add the plain text between the last tag and this one found
|
967
|
+
plainTextRepresentation += text.substring(parseIndex, foundHtmlTag.startIdx);
|
968
|
+
nextTag.plainTextBeginIndex = plainTextRepresentation.length;
|
969
|
+
if (foundHtmlTag.type === 'open') {
|
970
|
+
tagParseStack.push(nextTag);
|
971
|
+
}
|
972
|
+
else {
|
973
|
+
nextTag.content = '';
|
974
|
+
nextTag.plainTextBeginIndex = plainTextRepresentation.length;
|
975
|
+
nextTag.plainTextEndIndex = plainTextRepresentation.length;
|
976
|
+
addTag(nextTag, tagParseStack, tags);
|
977
|
+
}
|
978
|
+
}
|
979
|
+
if (foundHtmlTag.type === 'close') {
|
980
|
+
const currentOpenTag = tagParseStack.pop();
|
981
|
+
const closeTagType = foundHtmlTag.content.substring(2, foundHtmlTag.content.length - 1).toLowerCase();
|
982
|
+
if (currentOpenTag && currentOpenTag.tagType === closeTagType) {
|
983
|
+
// Tag startIdx is absolute to the text. This is updated later to be relative to the parent tag
|
984
|
+
currentOpenTag.content = text.substring(currentOpenTag.openTagIdx + currentOpenTag.openTagBody.length, foundHtmlTag.startIdx);
|
985
|
+
// Insert the plain text pieces for the sub tags
|
986
|
+
if (currentOpenTag.tagType === 'msft-mention') {
|
987
|
+
plainTextRepresentation =
|
988
|
+
plainTextRepresentation.slice(0, currentOpenTag.plainTextBeginIndex) +
|
989
|
+
trigger +
|
990
|
+
plainTextRepresentation.slice(currentOpenTag.plainTextBeginIndex);
|
991
|
+
}
|
992
|
+
if (!currentOpenTag.subTags) {
|
993
|
+
plainTextRepresentation += currentOpenTag.content;
|
994
|
+
}
|
995
|
+
else if (currentOpenTag.subTags.length > 0) {
|
996
|
+
// Add text after the last tag
|
997
|
+
const lastSubTag = currentOpenTag.subTags[currentOpenTag.subTags.length - 1];
|
998
|
+
const startOfRemainingText = ((_a = lastSubTag.closeTagIdx) !== null && _a !== void 0 ? _a : lastSubTag.openTagIdx) + lastSubTag.tagType.length + 3;
|
999
|
+
const trailingText = currentOpenTag.content.substring(startOfRemainingText);
|
1000
|
+
plainTextRepresentation += trailingText;
|
1001
|
+
}
|
1002
|
+
currentOpenTag.plainTextEndIndex = plainTextRepresentation.length;
|
1003
|
+
addTag(currentOpenTag, tagParseStack, tags);
|
1004
|
+
}
|
1005
|
+
else {
|
1006
|
+
console.error('Unexpected close tag found. Got "' +
|
1007
|
+
closeTagType +
|
1008
|
+
'" but expected "' +
|
1009
|
+
((_b = tagParseStack[tagParseStack.length - 1]) === null || _b === void 0 ? void 0 : _b.tagType) +
|
1010
|
+
'"');
|
1011
|
+
}
|
1012
|
+
}
|
1013
|
+
// Update parsing index; move past the end of the close tag
|
1014
|
+
parseIndex = foundHtmlTag.startIdx + foundHtmlTag.content.length;
|
1015
|
+
} // While parseIndex < text.length loop
|
1016
|
+
return [tags, plainTextRepresentation];
|
1017
|
+
};
|
1018
|
+
/* @conditional-compile-remove(mention) */
|
1019
|
+
const parseOpenTag = (tag, startIdx) => {
|
1020
|
+
const tagType = tag
|
1021
|
+
.substring(1, tag.length - 1)
|
1022
|
+
.split(' ')[0]
|
1023
|
+
.toLowerCase()
|
1024
|
+
.replace('/', '');
|
1025
|
+
return {
|
1026
|
+
tagType,
|
1027
|
+
openTagIdx: startIdx,
|
1028
|
+
openTagBody: tag
|
1029
|
+
};
|
1030
|
+
};
|
1031
|
+
/* @conditional-compile-remove(mention) */
|
1032
|
+
const findNextHtmlTag = (text, startIndex) => {
|
1033
|
+
const tagStartIndex = text.indexOf('<', startIndex);
|
1034
|
+
if (tagStartIndex === -1) {
|
1035
|
+
// No more tags
|
1036
|
+
return undefined;
|
1037
|
+
}
|
1038
|
+
const tagEndIndex = text.indexOf('>', tagStartIndex);
|
1039
|
+
if (tagEndIndex === -1) {
|
1040
|
+
// No close tag
|
1041
|
+
return undefined;
|
1042
|
+
}
|
1043
|
+
const tag = text.substring(tagStartIndex, tagEndIndex + 1);
|
1044
|
+
let type = 'open';
|
1045
|
+
if (tag[1] === '/') {
|
1046
|
+
type = 'close';
|
1047
|
+
}
|
1048
|
+
else if (tag[tag.length - 2] === '/') {
|
1049
|
+
type = 'self-closing';
|
1050
|
+
}
|
1051
|
+
return {
|
1052
|
+
content: tag,
|
1053
|
+
startIdx: tagStartIndex,
|
1054
|
+
type
|
1055
|
+
};
|
1056
|
+
};
|
1057
|
+
/* @conditional-compile-remove(mention) */
|
1058
|
+
const addTag = (tag, parseStack, tags) => {
|
1059
|
+
var _a;
|
1060
|
+
// Add as sub-tag to the parent stack tag, if there is one
|
1061
|
+
const parentTag = parseStack[parseStack.length - 1];
|
1062
|
+
if (parentTag) {
|
1063
|
+
// Adjust the open tag index to be relative to the parent tag
|
1064
|
+
const parentContentStartIdx = parentTag.openTagIdx + parentTag.openTagBody.length;
|
1065
|
+
const relativeIdx = tag.openTagIdx - parentContentStartIdx;
|
1066
|
+
tag.openTagIdx = relativeIdx;
|
1067
|
+
}
|
1068
|
+
if (!tag.closeTagIdx) {
|
1069
|
+
// If the tag is self-closing, the close tag is the same as the open tag
|
1070
|
+
if (tag.openTagBody[tag.openTagBody.length - 2] === '/') {
|
1071
|
+
tag.closeTagIdx = tag.openTagIdx;
|
1072
|
+
}
|
1073
|
+
else {
|
1074
|
+
// Otherwise, the close tag index is the open tag index + the open tag body + the content length
|
1075
|
+
tag.closeTagIdx = tag.openTagIdx + tag.openTagBody.length + ((_a = tag.content) !== null && _a !== void 0 ? _a : []).length;
|
1076
|
+
}
|
1077
|
+
}
|
1078
|
+
// Put the tag where it belongs
|
1079
|
+
if (!parentTag) {
|
1080
|
+
tags.push(tag);
|
1081
|
+
}
|
1082
|
+
else {
|
1083
|
+
if (!parentTag.subTags) {
|
1084
|
+
parentTag.subTags = [tag];
|
1085
|
+
}
|
1086
|
+
else {
|
1087
|
+
parentTag.subTags.push(tag);
|
1088
|
+
}
|
1089
|
+
}
|
1090
|
+
};
|
58
1091
|
//# sourceMappingURL=InputBoxComponent.js.map
|