dce-reactkit 3.8.6 → 3.9.0-beta-loading-modal.1
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/cjs/index.js +253 -381
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/Modal/ModalProps.d.ts +2 -0
- package/dist/cjs/types/index.d.ts +1 -3
- package/dist/esm/index.js +255 -381
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/Modal/ModalProps.d.ts +2 -0
- package/dist/esm/types/index.d.ts +1 -3
- package/dist/index.d.ts +45 -79
- package/package.json +1 -1
- package/src/components/Modal/ModalProps.ts +4 -0
- package/src/components/Modal/index.tsx +49 -21
- package/src/components/MultiSwitch.tsx +1 -1
- package/src/index.ts +0 -4
- package/dist/cjs/types/components/Dropdown.d.ts +0 -32
- package/dist/cjs/types/helpers/validators/ChicagoTitleCase.d.ts +0 -9
- package/dist/cjs/types/helpers/validators/validURL.d.ts +0 -8
- package/dist/cjs/types/types/DropdownItemType.d.ts +0 -6
- package/dist/esm/types/components/Dropdown.d.ts +0 -32
- package/dist/esm/types/helpers/validators/ChicagoTitleCase.d.ts +0 -9
- package/dist/esm/types/helpers/validators/validURL.d.ts +0 -8
- package/dist/esm/types/types/DropdownItemType.d.ts +0 -6
- package/src/components/Dropdown.tsx +0 -317
- package/src/helpers/validators/ChicagoTitleCase.test.ts +0 -85
- package/src/helpers/validators/ChicagoTitleCase.ts +0 -32
- package/src/helpers/validators/findURL.test.ts +0 -83
- package/src/helpers/validators/findURL.ts +0 -43
- package/src/helpers/validators/validURL.test.ts +0 -90
- package/src/helpers/validators/validURL.ts +0 -18
- package/src/types/DropdownItemType.ts +0 -11
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A simple dropdown menu
|
|
3
|
-
* @author Alessandra De Lucas
|
|
4
|
-
* @author Yuen Ler Chow
|
|
5
|
-
* @author Gabe Abrams
|
|
6
|
-
*/
|
|
7
|
-
import React from 'react';
|
|
8
|
-
import Variant from '../types/Variant';
|
|
9
|
-
import DropdownItemType from '../types/DropdownItemType';
|
|
10
|
-
type Props = {
|
|
11
|
-
items: DropdownItem[];
|
|
12
|
-
dropdownButton: {
|
|
13
|
-
ariaLabel: string;
|
|
14
|
-
id: string;
|
|
15
|
-
content?: React.ReactNode;
|
|
16
|
-
variant?: Variant;
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
type DropdownItem = ({
|
|
20
|
-
type: DropdownItemType.Header;
|
|
21
|
-
content: React.ReactNode;
|
|
22
|
-
} | {
|
|
23
|
-
type: DropdownItemType.Divider;
|
|
24
|
-
} | {
|
|
25
|
-
type: DropdownItemType.Item;
|
|
26
|
-
content: React.ReactNode;
|
|
27
|
-
ariaLabel: string;
|
|
28
|
-
id: string;
|
|
29
|
-
onClick: () => void;
|
|
30
|
-
});
|
|
31
|
-
declare const Dropdown: React.FC<Props>;
|
|
32
|
-
export default Dropdown;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This function converts a string to title case based on Chicago Title Case
|
|
3
|
-
* Style rules.
|
|
4
|
-
* @author Leisha Bhandari
|
|
5
|
-
* @param input: The input string that needs to be converted to Chicago title
|
|
6
|
-
* case.
|
|
7
|
-
* @returns Input string converted to title case
|
|
8
|
-
*/
|
|
9
|
-
declare const chicagoTitleCase: (input: string) => string;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This function checks if a given input string is a valid URL.
|
|
3
|
-
* @author Leisha Bhandari
|
|
4
|
-
* @param URL: The input string that needs checked as a URL or not.
|
|
5
|
-
* @returns A true boolean value if the input string is a valid URL, and a false
|
|
6
|
-
* boolean value if the input string is a invalid URL
|
|
7
|
-
*/
|
|
8
|
-
declare function isValid(url: string): boolean;
|
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A simple dropdown menu
|
|
3
|
-
* @author Alessandra De Lucas
|
|
4
|
-
* @author Yuen Ler Chow
|
|
5
|
-
* @author Gabe Abrams
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// Import React
|
|
9
|
-
import React, { useEffect, useReducer, useRef } from 'react';
|
|
10
|
-
|
|
11
|
-
// Import helpers
|
|
12
|
-
import combineClassNames from '../helpers/combineClassNames';
|
|
13
|
-
|
|
14
|
-
// Import shared types
|
|
15
|
-
import Variant from '../types/Variant';
|
|
16
|
-
import DropdownItemType from '../types/DropdownItemType';
|
|
17
|
-
|
|
18
|
-
// Check dark mode
|
|
19
|
-
import { isDarkModeOn } from '../client/initClient';
|
|
20
|
-
|
|
21
|
-
/*------------------------------------------------------------------------*/
|
|
22
|
-
/* -------------------------------- Types ------------------------------- */
|
|
23
|
-
/*------------------------------------------------------------------------*/
|
|
24
|
-
|
|
25
|
-
// Props definition
|
|
26
|
-
type Props = {
|
|
27
|
-
// List of items in the dropdown menu
|
|
28
|
-
items: DropdownItem[],
|
|
29
|
-
// Information about the dropdown button
|
|
30
|
-
dropdownButton: {
|
|
31
|
-
// Aria label for accessibility
|
|
32
|
-
ariaLabel: string,
|
|
33
|
-
// Unique ID
|
|
34
|
-
id: string,
|
|
35
|
-
// Button content
|
|
36
|
-
content?: React.ReactNode,
|
|
37
|
-
// Variant
|
|
38
|
-
variant?: Variant,
|
|
39
|
-
},
|
|
40
|
-
// If true, no arrow shows in dropdown
|
|
41
|
-
// noArrow?: boolean,
|
|
42
|
-
// Size of dropdown
|
|
43
|
-
// size?: DropdownSize,
|
|
44
|
-
// Direction of dropdown
|
|
45
|
-
// direction?: DropdownDirection,
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// Details about a dropdown item
|
|
49
|
-
type DropdownItem = (
|
|
50
|
-
| {
|
|
51
|
-
// Header element
|
|
52
|
-
type: DropdownItemType.Header,
|
|
53
|
-
// Header content
|
|
54
|
-
content: React.ReactNode,
|
|
55
|
-
}
|
|
56
|
-
| {
|
|
57
|
-
// Divider element
|
|
58
|
-
type: DropdownItemType.Divider,
|
|
59
|
-
}
|
|
60
|
-
| {
|
|
61
|
-
// Item from dropdown menu
|
|
62
|
-
type: DropdownItemType.Item,
|
|
63
|
-
// Item content
|
|
64
|
-
content: React.ReactNode,
|
|
65
|
-
// Item aria label
|
|
66
|
-
ariaLabel: string,
|
|
67
|
-
// Unique item ID
|
|
68
|
-
id: string,
|
|
69
|
-
// Click function for dropdown item
|
|
70
|
-
onClick: () => void,
|
|
71
|
-
}
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
// Dropdown menu sizes
|
|
75
|
-
// enum DropdownSize {
|
|
76
|
-
// // Small dropdown size
|
|
77
|
-
// Small = 'Small',
|
|
78
|
-
// // Medium dropdown size
|
|
79
|
-
// Medium = 'Medium',
|
|
80
|
-
// // Large dropdown size
|
|
81
|
-
// Large = 'Large',
|
|
82
|
-
// }
|
|
83
|
-
|
|
84
|
-
// Dropdown menu direction
|
|
85
|
-
// enum DropdownDirection {
|
|
86
|
-
// // Dropdown menu appears centered
|
|
87
|
-
// Centered = 'Centered',
|
|
88
|
-
// // Dropdown menu appears to right of button
|
|
89
|
-
// Right = 'Right',
|
|
90
|
-
// // Dropdown menu appears to left of button
|
|
91
|
-
// Left = 'Left',
|
|
92
|
-
// // Dropdown menu appears above the button
|
|
93
|
-
// Up = 'Up',
|
|
94
|
-
// // Dropdown menu appears below the button
|
|
95
|
-
// Down = 'Down',
|
|
96
|
-
// }
|
|
97
|
-
|
|
98
|
-
/*------------------------------------------------------------------------*/
|
|
99
|
-
/* -------------------------------- State ------------------------------- */
|
|
100
|
-
/*------------------------------------------------------------------------*/
|
|
101
|
-
|
|
102
|
-
/* -------- State Definition -------- */
|
|
103
|
-
|
|
104
|
-
type State = {
|
|
105
|
-
// If true, the dropdown menu is open
|
|
106
|
-
isDropdownOpen: boolean,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
/* ------------- Actions ------------ */
|
|
110
|
-
|
|
111
|
-
// Types of actions
|
|
112
|
-
enum ActionType {
|
|
113
|
-
// Toggle opening the dropdown menu
|
|
114
|
-
ToggleDropdown = 'ToggleDropdown',
|
|
115
|
-
// Close the dropdown menu
|
|
116
|
-
CloseDropdown = 'CloseDropdown',
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Action definitions
|
|
120
|
-
type Action = (
|
|
121
|
-
| {
|
|
122
|
-
type: ActionType.ToggleDropdown,
|
|
123
|
-
}
|
|
124
|
-
| {
|
|
125
|
-
type: ActionType.CloseDropdown,
|
|
126
|
-
}
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Reducer that executes actions
|
|
131
|
-
* @author Alessandra De Lucas
|
|
132
|
-
* @author Yuen Ler Chow
|
|
133
|
-
* @param state current state
|
|
134
|
-
* @param action action to execute
|
|
135
|
-
*/
|
|
136
|
-
const reducer = (state: State, action: Action): State => {
|
|
137
|
-
switch (action.type) {
|
|
138
|
-
case ActionType.ToggleDropdown: {
|
|
139
|
-
return {
|
|
140
|
-
...state,
|
|
141
|
-
isDropdownOpen: !state.isDropdownOpen,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
case ActionType.CloseDropdown: {
|
|
145
|
-
return {
|
|
146
|
-
...state,
|
|
147
|
-
isDropdownOpen: false,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
default: {
|
|
151
|
-
return state;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
/*------------------------------------------------------------------------*/
|
|
157
|
-
/* ------------------------------ Component ----------------------------- */
|
|
158
|
-
/*------------------------------------------------------------------------*/
|
|
159
|
-
|
|
160
|
-
const Dropdown: React.FC<Props> = (props) => {
|
|
161
|
-
/*------------------------------------------------------------------------*/
|
|
162
|
-
/* -------------------------------- Setup ------------------------------- */
|
|
163
|
-
/*------------------------------------------------------------------------*/
|
|
164
|
-
|
|
165
|
-
/* -------------- Props ------------- */
|
|
166
|
-
|
|
167
|
-
// Destructure all props
|
|
168
|
-
const {
|
|
169
|
-
dropdownButton,
|
|
170
|
-
items,
|
|
171
|
-
} = props;
|
|
172
|
-
|
|
173
|
-
/* -------------- State ------------- */
|
|
174
|
-
|
|
175
|
-
// Initial state
|
|
176
|
-
const initialState: State = {
|
|
177
|
-
isDropdownOpen: false,
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
// Initialize state
|
|
181
|
-
const [state, dispatch] = useReducer(reducer, initialState);
|
|
182
|
-
|
|
183
|
-
// Destructure common state
|
|
184
|
-
const {
|
|
185
|
-
isDropdownOpen,
|
|
186
|
-
} = state;
|
|
187
|
-
|
|
188
|
-
/* -------------- Refs -------------- */
|
|
189
|
-
|
|
190
|
-
// Initialize refs
|
|
191
|
-
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
192
|
-
|
|
193
|
-
/*------------------------------------------------------------------------*/
|
|
194
|
-
/* ------------------------- Component Functions ------------------------ */
|
|
195
|
-
/*------------------------------------------------------------------------*/
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Handle clicking outside of the dropdown menu to close it
|
|
199
|
-
* @author Yuen Ler Chow
|
|
200
|
-
* @param event the mouse event
|
|
201
|
-
*/
|
|
202
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
203
|
-
if (
|
|
204
|
-
// Dropdown has been rendered
|
|
205
|
-
dropdownRef.current
|
|
206
|
-
// Click occurred outside the dropdown
|
|
207
|
-
&& !dropdownRef.current.contains(event.target as Element)
|
|
208
|
-
) {
|
|
209
|
-
dispatch({ type: ActionType.CloseDropdown });
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
/*------------------------------------------------------------------------*/
|
|
214
|
-
/* ------------------------- Lifecycle Functions ------------------------ */
|
|
215
|
-
/*------------------------------------------------------------------------*/
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Mount
|
|
219
|
-
* @author Yuen Ler Chow
|
|
220
|
-
*/
|
|
221
|
-
useEffect(() => {
|
|
222
|
-
// Add event listener to close dropdown when clicking outside
|
|
223
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
224
|
-
|
|
225
|
-
// Cleanup
|
|
226
|
-
return () => {
|
|
227
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
228
|
-
};
|
|
229
|
-
}, []);
|
|
230
|
-
|
|
231
|
-
/*----------------------------------------*/
|
|
232
|
-
/* --------------- Main UI -------------- */
|
|
233
|
-
/*----------------------------------------*/
|
|
234
|
-
|
|
235
|
-
return (
|
|
236
|
-
<div
|
|
237
|
-
className="dropdown"
|
|
238
|
-
ref={dropdownRef}
|
|
239
|
-
data-bs-theme={isDarkModeOn() ? 'dark' : undefined}
|
|
240
|
-
>
|
|
241
|
-
<button
|
|
242
|
-
className={
|
|
243
|
-
combineClassNames([
|
|
244
|
-
'btn dropdown-toggle border',
|
|
245
|
-
isDropdownOpen && 'show',
|
|
246
|
-
`btn-${dropdownButton.variant}`,
|
|
247
|
-
dropdownButton.variant === Variant.Light && 'text-dark',
|
|
248
|
-
])
|
|
249
|
-
}
|
|
250
|
-
type="button"
|
|
251
|
-
id={dropdownButton.id}
|
|
252
|
-
aria-expanded={isDropdownOpen}
|
|
253
|
-
aria-label={dropdownButton.ariaLabel}
|
|
254
|
-
onClick={() => {
|
|
255
|
-
dispatch({
|
|
256
|
-
type: ActionType.ToggleDropdown,
|
|
257
|
-
});
|
|
258
|
-
}}
|
|
259
|
-
>
|
|
260
|
-
{
|
|
261
|
-
dropdownButton.content
|
|
262
|
-
}
|
|
263
|
-
</button>
|
|
264
|
-
<ul
|
|
265
|
-
className={
|
|
266
|
-
combineClassNames([
|
|
267
|
-
'dropdown-menu',
|
|
268
|
-
isDarkModeOn() && 'dropdown-menu-dark',
|
|
269
|
-
isDropdownOpen && 'show',
|
|
270
|
-
])
|
|
271
|
-
}
|
|
272
|
-
>
|
|
273
|
-
{Object.values(items).map((item) => {
|
|
274
|
-
if (item.type === DropdownItemType.Header) {
|
|
275
|
-
return (
|
|
276
|
-
// TODO: Implement header
|
|
277
|
-
<span />
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
if (item.type === DropdownItemType.Divider) {
|
|
281
|
-
return (
|
|
282
|
-
// TODO: Implement divider
|
|
283
|
-
<span />
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
return (
|
|
287
|
-
<li
|
|
288
|
-
key={item.id}
|
|
289
|
-
>
|
|
290
|
-
<button
|
|
291
|
-
type="button"
|
|
292
|
-
aria-label={item.ariaLabel}
|
|
293
|
-
className="dropdown-item"
|
|
294
|
-
onClick={(e) => {
|
|
295
|
-
e.preventDefault();
|
|
296
|
-
dispatch({
|
|
297
|
-
type: ActionType.CloseDropdown,
|
|
298
|
-
});
|
|
299
|
-
item.onClick();
|
|
300
|
-
}}
|
|
301
|
-
>
|
|
302
|
-
{item.content}
|
|
303
|
-
</button>
|
|
304
|
-
</li>
|
|
305
|
-
);
|
|
306
|
-
})}
|
|
307
|
-
</ul>
|
|
308
|
-
</div>
|
|
309
|
-
);
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
/*------------------------------------------------------------------------*/
|
|
313
|
-
/* ------------------------------- Wrap Up ------------------------------ */
|
|
314
|
-
/*------------------------------------------------------------------------*/
|
|
315
|
-
|
|
316
|
-
// Export component
|
|
317
|
-
export default Dropdown;
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// Importing the testing function
|
|
2
|
-
// import chicagoTitleCase from './chicagoTitleCase';
|
|
3
|
-
|
|
4
|
-
// // Import constants
|
|
5
|
-
// import { INVALID_STRING_ERRORS, INVALID_REGEX_ERROR } from './shared/constants/ERROR_MESSAGES';
|
|
6
|
-
|
|
7
|
-
// /*------------------------------------------------------------------------*/
|
|
8
|
-
// /* ---------------------------- Valid Tests --------------------------- */
|
|
9
|
-
// /*------------------------------------------------------------------------*/
|
|
10
|
-
|
|
11
|
-
// const validTests: { input: string, expected: string }[] = [
|
|
12
|
-
// {
|
|
13
|
-
// input: 'this is the american language',
|
|
14
|
-
// expected: 'This the American language',
|
|
15
|
-
// },
|
|
16
|
-
// {
|
|
17
|
-
// input: 'to kill a mockingbird',
|
|
18
|
-
// expected: 'To Kill a Mockingbird',
|
|
19
|
-
// },
|
|
20
|
-
// {
|
|
21
|
-
// input: 'the lord of the rings',
|
|
22
|
-
// expected: 'The Lord of the Rings',
|
|
23
|
-
// },
|
|
24
|
-
// {
|
|
25
|
-
// input: 'pride and prejudice',
|
|
26
|
-
// expected: 'Pride and Prejudice',
|
|
27
|
-
// },
|
|
28
|
-
// {
|
|
29
|
-
// input: 'the road not taken',
|
|
30
|
-
// expected: 'The Road Not Taken',
|
|
31
|
-
// },
|
|
32
|
-
// ];
|
|
33
|
-
|
|
34
|
-
// test(
|
|
35
|
-
// 'Converts strings to Chicago title case correctly.',
|
|
36
|
-
// async () => {
|
|
37
|
-
// validTests.forEach(({ input, expected }) => {
|
|
38
|
-
// expect(chicagoTitleCase(input)).toBe(expected);
|
|
39
|
-
// });
|
|
40
|
-
// },
|
|
41
|
-
// );
|
|
42
|
-
|
|
43
|
-
// /*------------------------------------------------------------------------*/
|
|
44
|
-
// /* ---------------------------- Edge Cases ---------------------------- */
|
|
45
|
-
// /*------------------------------------------------------------------------*/
|
|
46
|
-
|
|
47
|
-
// const edgeCases: { input: string, expected: string }[] = [
|
|
48
|
-
// {
|
|
49
|
-
// input: 'x',
|
|
50
|
-
// expected: 'X',
|
|
51
|
-
// },
|
|
52
|
-
// {
|
|
53
|
-
// input: ' ',
|
|
54
|
-
// expected: ' ',
|
|
55
|
-
// },
|
|
56
|
-
// {
|
|
57
|
-
// input: '',
|
|
58
|
-
// expected: '',
|
|
59
|
-
// },
|
|
60
|
-
// {
|
|
61
|
-
// input: 'the',
|
|
62
|
-
// expected: 'The',
|
|
63
|
-
// },
|
|
64
|
-
// {
|
|
65
|
-
// input: 'THE ROAD NOT TAKEN',
|
|
66
|
-
// expected: 'The Road Not Taken',
|
|
67
|
-
// },
|
|
68
|
-
// {
|
|
69
|
-
// input: 'tO kiLL A mOckingBirD',
|
|
70
|
-
// expected: 'To Kill a Mockingbird',
|
|
71
|
-
// },
|
|
72
|
-
// {
|
|
73
|
-
// input: 'pRiDe And pReduJiCe',
|
|
74
|
-
// expected: 'Pride and Prejudice',
|
|
75
|
-
// },
|
|
76
|
-
// ];
|
|
77
|
-
|
|
78
|
-
// test(
|
|
79
|
-
// 'Handles the edge cases for the function that converts a string to Chicago Title Case.',
|
|
80
|
-
// async () => {
|
|
81
|
-
// edgeCases.forEach(({ input, expected }) => {
|
|
82
|
-
// expect(chicagoTitleCase(input)).toBe(expected);
|
|
83
|
-
// });
|
|
84
|
-
// },
|
|
85
|
-
// );
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This function converts a string to title case based on Chicago Title Case
|
|
3
|
-
* Style rules.
|
|
4
|
-
* @author Leisha Bhandari
|
|
5
|
-
* @param input: The input string that needs to be converted to Chicago title
|
|
6
|
-
* case.
|
|
7
|
-
* @returns Input string converted to title case
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const chicagoTitleCase = (input: string): string => {
|
|
12
|
-
// List of lowercase words according to Chicago Manual of Style
|
|
13
|
-
const lowerCaseWords: string[] = [
|
|
14
|
-
'in', 'nor', 'of', 'on', 'or', 'as', 'at', 'but', 'by',
|
|
15
|
-
'for', 'if', 'so', 'the', 'a', 'an', 'and', 'to', 'up',
|
|
16
|
-
'yet'
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
return input
|
|
20
|
-
// Converts given input string to lowercase
|
|
21
|
-
.toLowerCase()
|
|
22
|
-
// Splits the given string into separate words
|
|
23
|
-
.split(' ')
|
|
24
|
-
.map((word, index, words) =>
|
|
25
|
-
// Capitalize the first word, last word, and the words that aren't
|
|
26
|
-
// in lowerCaseWords
|
|
27
|
-
index === 0 || !lowerCaseWords.includes(word) || index === words.length - 1
|
|
28
|
-
? `${word.charAt(0).toUpperCase()}${word.slice(1)}` // Capitalize the first letter
|
|
29
|
-
: word // Nothing happens to the word
|
|
30
|
-
)
|
|
31
|
-
.join(' '); // Joins the words back
|
|
32
|
-
};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
// Import the function to be tested
|
|
2
|
-
// import findURLs from './findURL';
|
|
3
|
-
|
|
4
|
-
// // Import constants
|
|
5
|
-
// import { INVALID_STRING_ERRORS, INVALID_REGEX_ERROR } from './shared/constants/ERROR_MESSAGES';
|
|
6
|
-
|
|
7
|
-
// /*------------------------------------------------------------------------*/
|
|
8
|
-
// /* ---------------------------- Valid Tests --------------------------- */
|
|
9
|
-
// /*------------------------------------------------------------------------*/
|
|
10
|
-
|
|
11
|
-
// const validTests: { block: string, expected: { start: number, end: number }[] }[] = [
|
|
12
|
-
// {
|
|
13
|
-
// block: 'Visit http://example.com for more information.',
|
|
14
|
-
// expected: [{ start: 6, end: 23 }],
|
|
15
|
-
// },
|
|
16
|
-
// {
|
|
17
|
-
// block: 'Multiple URLs: http://one.com and http://two.com.',
|
|
18
|
-
// expected: [
|
|
19
|
-
// { start: 15, end: 29 },
|
|
20
|
-
// { start: 34, end: 48 },
|
|
21
|
-
// ],
|
|
22
|
-
// },
|
|
23
|
-
// {
|
|
24
|
-
// block: 'Localhost URLs: http://localhost and http://127.0.0.1.',
|
|
25
|
-
// expected: [
|
|
26
|
-
// { start: 16, end: 31 },
|
|
27
|
-
// { start: 36, end: 52 },
|
|
28
|
-
// ],
|
|
29
|
-
// },
|
|
30
|
-
// {
|
|
31
|
-
// block: 'Embedded URL: text https://embedded-url.com?query=1&value=2.',
|
|
32
|
-
// expected: [{ start: 13, end: 51 }],
|
|
33
|
-
// },
|
|
34
|
-
// {
|
|
35
|
-
// block: 'Secure site: https://secure-site.com/path?query=string#fragment',
|
|
36
|
-
// expected: [{ start: 13, end: 58 }],
|
|
37
|
-
// },
|
|
38
|
-
// ];
|
|
39
|
-
|
|
40
|
-
// test(
|
|
41
|
-
// 'Returns correct start and end indices for valid URLs within a string.',
|
|
42
|
-
// async () => {
|
|
43
|
-
// validTests.forEach(({ block, expected }) => {
|
|
44
|
-
// expect(findURLs(block)).toStrictEqual(expected);
|
|
45
|
-
// });
|
|
46
|
-
// },
|
|
47
|
-
// );
|
|
48
|
-
|
|
49
|
-
// /*------------------------------------------------------------------------*/
|
|
50
|
-
// /* ---------------------------- Invalid Tests --------------------------- */
|
|
51
|
-
// /*------------------------------------------------------------------------*/
|
|
52
|
-
|
|
53
|
-
// const invalidTests: { block: string, expected: { start: number, end: number }[] }[] = [
|
|
54
|
-
// {
|
|
55
|
-
// block: 'No URL.',
|
|
56
|
-
// expected: [],
|
|
57
|
-
// },
|
|
58
|
-
// {
|
|
59
|
-
// block: 'URL format is wrong: http:/example.com and htt://example.com.',
|
|
60
|
-
// expected: [],
|
|
61
|
-
// },
|
|
62
|
-
// {
|
|
63
|
-
// block: 'Any punctuation after the URL http://example.com, should not count.',
|
|
64
|
-
// expected: [{ start: 20, end: 37 }],
|
|
65
|
-
// },
|
|
66
|
-
// {
|
|
67
|
-
// block: 'Starting punctuation ,http://example.com should not count.',
|
|
68
|
-
// expected: [{ start: 22, end: 39 }],
|
|
69
|
-
// },
|
|
70
|
-
// {
|
|
71
|
-
// block: 'Spaces in the middle http://exa mple.com is invalid.',
|
|
72
|
-
// expected: [],
|
|
73
|
-
// },
|
|
74
|
-
// ];
|
|
75
|
-
|
|
76
|
-
// test(
|
|
77
|
-
// 'Returns empty array for strings without valid URLs.',
|
|
78
|
-
// async () => {
|
|
79
|
-
// invalidTests.forEach(({ block, expected }) => {
|
|
80
|
-
// expect(findURLs(block)).toStrictEqual(expected);
|
|
81
|
-
// });
|
|
82
|
-
// },
|
|
83
|
-
// );
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// /**
|
|
2
|
-
// * This function finds URLs within a given string and returns an array of
|
|
3
|
-
// * their locations.
|
|
4
|
-
// * @author Leisha Bhandari
|
|
5
|
-
// * @param block: The block of text to search for URLs
|
|
6
|
-
// * @returns Arrays where each of them contain the start and end index of the URL
|
|
7
|
-
// */
|
|
8
|
-
// function findURLs(block: string): { start: number, end: number }[] {
|
|
9
|
-
// // Expression representing the skeleton of a URL to help match and find the
|
|
10
|
-
// // URLs within the block of text (Also takes care of Unicode characters)
|
|
11
|
-
// const urlSkeleton = /(https?:\/\/[^\s\u0000-\u001F.,]+[^\s\u0000-\u001F.,]?(?:\?[^\s\u0000-\u001F]+)?(?:#[^\s\u0000-\u001F]+)?)/g;
|
|
12
|
-
// const found: { start: number, end: number }[] = [];
|
|
13
|
-
// let match: RegExpExecArray | null;
|
|
14
|
-
|
|
15
|
-
// // While loop to find the URLs in the given block of texts using the URL
|
|
16
|
-
// // skeleton
|
|
17
|
-
// while ((match === urlSkeleton.exec(block))
|
|
18
|
-
// && match !== null) {
|
|
19
|
-
// // To find the beginning index of the URL
|
|
20
|
-
// let start = match.index;
|
|
21
|
-
// // To find the last index of the URL
|
|
22
|
-
// let end = match.index + match[0].length;
|
|
23
|
-
|
|
24
|
-
// // If statements to check whether the URL is followed by some kind of
|
|
25
|
-
// // punctuation mark
|
|
26
|
-
// if (block.charAt(end) === '.' || /[,;:!?"]/.test(block.charAt(end))) {
|
|
27
|
-
// end--;
|
|
28
|
-
// }
|
|
29
|
-
|
|
30
|
-
// // While statement to make sure that the URL does not start with a
|
|
31
|
-
// // punctuation mark
|
|
32
|
-
// while (start > 0 && /[.,:;!?]/.test(block.charAt(start - 1))) {
|
|
33
|
-
// start--;
|
|
34
|
-
// }
|
|
35
|
-
|
|
36
|
-
// // The object with start and end index of the URL is found and pushed to
|
|
37
|
-
// // the found array
|
|
38
|
-
// found.push({ start, end });
|
|
39
|
-
// }
|
|
40
|
-
|
|
41
|
-
// // Returns the array of the found URLs location
|
|
42
|
-
// return found;
|
|
43
|
-
// }
|