react-native-enriched 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -1,6 +1,8 @@
1
+ <img src="https://github.com/user-attachments/assets/abc75d3b-495b-4a76-a72f-d87ce3ca1ff9" alt="react-native-enriched by Software Mansion" width="100%">
2
+
1
3
  # react-native-enriched
2
4
 
3
- `react-native-enriched` is a powerful React Native library that shares a rich text editor component:
5
+ `react-native-enriched` is a powerful React Native library that exposes a rich text editor component:
4
6
 
5
7
  - ⚡ Fully native text input component
6
8
  - đŸ•šī¸ Synchronous text styling
@@ -9,26 +11,37 @@
9
11
  - 📱 Mobile platforms support
10
12
  - 🏛 Supports only the New Architecture
11
13
 
12
- `EnrichedTextInput`, the rich text editor component that the library shares is an uncontrolled input. This means that it doesn't use any state or props to store its value, but instead directly interacts with the underlying platform-specific components. Thanks to this, the component is really performant and simple to use while offering complex and advanced features no other solution has.
14
+ `EnrichedTextInput`, the rich text editor component is an uncontrolled input. This means that it doesn't use any state or props to store its value, but instead directly interacts with the underlying platform-specific components. Thanks to this, the component is really performant and simple to use while offering complex and advanced features no other solution has.
13
15
 
14
16
  Built by [Software Mansion](https://swmansion.com/) and sponsored by [Filament](https://filament.dm/).
15
17
 
18
+ <img width="128" height="69" alt="Software Mansion Logo" src="https://github.com/user-attachments/assets/f0e18471-a7aa-4e80-86ac-87686a86fe56" />
19
+ &nbsp;&nbsp;&nbsp;
20
+ <img width="48" height="48" alt="" src="https://github.com/user-attachments/assets/46c6bf1f-2685-497e-b699-d5a94b2582a3" />
21
+ &nbsp;&nbsp;&nbsp;
22
+ <img width="80" height="80" alt="Filament Logo" src="https://github.com/user-attachments/assets/4103ab79-da34-4164-aa5f-dcf08815bf65" />
23
+
24
+ \
25
+ Since 2012 [Software Mansion](https://swmansion.com) is a software agency with experience in building web and mobile apps. We are Core React Native Contributors and experts in dealing with all kinds of React Native issues.
26
+ We can help you build your next dream product –
27
+ [Hire us](https://swmansion.com/contact/projects?utm_source=react-native-enriched&utm_medium=readme).
28
+
16
29
  ## Table of Contents
17
30
 
18
- 1. [Prerequisites](#prerequisites)
19
- 2. [Installation](#installation)
20
- 3. [Usage](#usage)
21
- 4. [Non Parametrized Styles](#non-parametrized-styles)
22
- 5. [Links](#links)
23
- 6. [Mentions](#mentions)
24
- 7. [Inline Images](#inline-images)
25
- 8. [Style Detection](#style-detection)
26
- 9. [Other Events](#other-events)
27
- 10. [Customizing \<EnrichedTextInput /> styles](#customizing-enrichedtextinput--styles)
28
- 11. [API Reference](#api-reference)
29
- 12. [Future Plans](#future-plans)
30
- 13. [Contributing](#contributing)
31
- 14. [License](#license)
31
+ - [Prerequisites](#prerequisites)
32
+ - [Installation](#installation)
33
+ - [Usage](#usage)
34
+ - [Non Parametrized Styles](#non-parametrized-styles)
35
+ - [Links](#links)
36
+ - [Mentions](#mentions)
37
+ - [Inline Images](#inline-images)
38
+ - [Style Detection](#style-detection)
39
+ - [Other Events](#other-events)
40
+ - [Customizing \<EnrichedTextInput /> styles](#customizing-enrichedtextinput--styles)
41
+ - [API Reference](#api-reference)
42
+ - [Future Plans](#future-plans)
43
+ - [Contributing](#contributing)
44
+ - [License](#license)
32
45
 
33
46
  ## Prerequisites
34
47
 
@@ -113,10 +126,11 @@ const styles = StyleSheet.create({
113
126
  alignItems: 'center',
114
127
  },
115
128
  input: {
129
+ width: '100%',
116
130
  fontSize: 20,
117
- padding: 20,
131
+ padding: 10,
118
132
  maxHeight: 200,
119
- borderWidth: 1,
133
+ backgroundColor: 'lightgray',
120
134
  },
121
135
  });
122
136
 
@@ -158,7 +172,7 @@ If the selection spans more than one paragraph, logically more of them will be a
158
172
 
159
173
  ## Links
160
174
 
161
- The links are here, just like in any other editor, a piece of text with a URL attribtued to it. They can be added in two ways: automatically or manually.
175
+ The links are here, just like in any other editor, a piece of text with a URL attributed to it. They can be added in two ways: automatically or manually.
162
176
 
163
177
  ### Automatic links detection
164
178
 
@@ -218,7 +232,7 @@ You can find some examples in the [usage section](#usage) or in the example app.
218
232
  `react-native-enriched` emits a few more events that may be of use:
219
233
 
220
234
  - [onFocus](#onfocus) - emits whenever input focuses.
221
- - [onBlur](#onblur) - emits whenver input blurs.
235
+ - [onBlur](#onblur) - emits whenever input blurs.
222
236
  - [onChangeText](#onchangetext) - returns the input's text anytime it changes.
223
237
  - [onChangeHtml](#onchangehtml) - returns HTML string parsed from current input text and styles anytime it would change. As parsing the HTML on each input change is a pretty expensive operation, not assigning the event's callback will speed up iOS input a bit. We are considering adding some API to improve it, see [future plans](#future-plans).
224
238
  - [onChangeSelection](#onchangeselection) - returns all the data needed for working with selections (as of now it's mainly useful for [links](#links)).
@@ -237,9 +251,9 @@ You can find some examples in the [usage section](#usage) or in the example app.
237
251
 
238
252
  If `true`, focuses the input.
239
253
 
240
- | Type | Default Value | Platform |
241
- | ---- | ------------- | -------- |
242
- | `bool` | `false` | Both |
254
+ | Type | Default Value | Platform |
255
+ |--------|---------------|----------|
256
+ | `bool` | `false` | Both |
243
257
 
244
258
  #### `autoCapitalize`
245
259
 
@@ -250,57 +264,57 @@ Tells input to automatically capitalize certain characters.
250
264
  - `sentences`: first letter of each sentence.
251
265
  - `none`: don't auto capitalize anything.
252
266
 
253
- | Type | Default Value | Platform |
254
- | ---- | ------------- | -------- |
255
- | `'none' \| 'sentences' \| 'words' \| 'characters'` | `'sentences'` | Both |
267
+ | Type | Default Value | Platform |
268
+ |----------------------------------------------------|---------------|----------|
269
+ | `'none' \| 'sentences' \| 'words' \| 'characters'` | `'sentences'` | Both |
256
270
 
257
271
  #### `cursorColor`
258
272
 
259
273
  When provided it will set the color of the cursor (or "caret") in the component.
260
274
 
261
- | Type | Default Value | Platform |
262
- | ---- | ------------- | -------- |
263
- | [`color`](https://reactnative.dev/docs/colors) | system default | Android |
275
+ | Type | Default Value | Platform |
276
+ |------------------------------------------------|----------------|----------|
277
+ | [`color`](https://reactnative.dev/docs/colors) | system default | Android |
264
278
 
265
279
  #### `defaultValue`
266
280
 
267
281
  Provides an initial value for the input. If the string is a valid HTML output of the `EnrichedTextInput` component (or other HTML that the parser will accept), proper styles will be applied.
268
282
 
269
- | Type | Default Value | Platform |
270
- | ---- | ------------- | -------- |
271
- | `string` | - | Both |
283
+ | Type | Default Value | Platform |
284
+ |----------|---------------|----------|
285
+ | `string` | - | Both |
272
286
 
273
287
  #### `editable`
274
288
 
275
289
  If `false`, text is not editable.
276
290
 
277
- | Type | Default Value | Platform |
278
- | ---- | ------------- | -------- |
279
- | `bool` | `true` | Both |
291
+ | Type | Default Value | Platform |
292
+ |--------|---------------|----------|
293
+ | `bool` | `true` | Both |
280
294
 
281
295
  #### `htmlStyle`
282
296
 
283
297
  A prop for customizing styles' appearances.
284
298
 
285
- | Type | Default Value | Platform |
286
- | ---- | ------------- | -------- |
287
- | [`HtmlStyle`](#htmlstyle-type) | default values from [`HtmlStyle`](#htmlstyle-type) | Both |
299
+ | Type | Default Value | Platform |
300
+ |--------------------------------|----------------------------------------------------|----------|
301
+ | [`HtmlStyle`](#htmlstyle-type) | default values from [`HtmlStyle`](#htmlstyle-type) | Both |
288
302
 
289
303
  #### `mentionIndicators`
290
304
 
291
305
  The recognized mention indicators. Each item needs to be a 1 character long string.
292
306
 
293
- | Type | Default Value | Platform |
294
- | ---- | ------------- | -------- |
295
- | array of `string` | `['@']` | Both |
307
+ | Type | Default Value | Platform |
308
+ |-------------------|---------------|----------|
309
+ | array of `string` | `['@']` | Both |
296
310
 
297
311
  #### `onBlur`
298
312
 
299
313
  Callback that's called whenever the input loses focused (is blurred).
300
314
 
301
- | Type | Default Value | Platform |
302
- | ---- | ------------- | -------- |
303
- | `() => void` | - | Both |
315
+ | Type | Default Value | Platform |
316
+ |--------------|---------------|----------|
317
+ | `() => void` | - | Both |
304
318
 
305
319
  #### `onChangeHtml`
306
320
 
@@ -316,9 +330,9 @@ interface OnChangeHtmlEvent {
316
330
 
317
331
  - `value` is the new HTML.
318
332
 
319
- | Type | Default Value | Platform |
320
- | ---- | ------------- | -------- |
321
- | `(NativeSyntheticEvent\<OnChangeHtmlEvent>) => void` | - | Both |
333
+ | Type | Default Value | Platform |
334
+ |------------------------------------------------------|---------------|----------|
335
+ | `(NativeSyntheticEvent\<OnChangeHtmlEvent>) => void` | - | Both |
322
336
 
323
337
  #### `onChangeMention`
324
338
 
@@ -336,9 +350,9 @@ interface OnChangeMentionEvent {
336
350
  - `indicator` is the indicator of the currently edited mention.
337
351
  - `text` contains whole text that has been typed after the indicator.
338
352
 
339
- | Type | Default Value | Platform |
340
- | ---- | ------------- | -------- |
341
- | `(OnChangeMentionEvent) => void` | - | Both |
353
+ | Type | Default Value | Platform |
354
+ |----------------------------------|---------------|----------|
355
+ | `(OnChangeMentionEvent) => void` | - | Both |
342
356
 
343
357
  #### `onChangeSelection`
344
358
 
@@ -358,9 +372,9 @@ OnChangeSelectionEvent {
358
372
  - `end` is the first index after the selection's ending. For just a cursor in place (no selection), `start` equals `end`.
359
373
  - `text` is the input's text in the current selection.
360
374
 
361
- | Type | Default Value | Platform |
362
- | ---- | ------------- | -------- |
363
- | `(NativeSyntheticEvent\<OnChangeSelectionEvent>) => void` | - | Both |
375
+ | Type | Default Value | Platform |
376
+ |-----------------------------------------------------------|---------------|----------|
377
+ | `(NativeSyntheticEvent\<OnChangeSelectionEvent>) => void` | - | Both |
364
378
 
365
379
  #### `onChangeState`
366
380
 
@@ -388,9 +402,9 @@ interface OnChangeStateEvent {
388
402
  }
389
403
  ```
390
404
 
391
- | Type | Default Value | Platform |
392
- | ---- | ------------- | -------- |
393
- | `(NativeSyntheticEvent\<OnChangeStateEvent>) => void` | - | Both |
405
+ | Type | Default Value | Platform |
406
+ |-------------------------------------------------------|---------------|----------|
407
+ | `(NativeSyntheticEvent\<OnChangeStateEvent>) => void` | - | Both |
394
408
 
395
409
  #### `onChangeText`
396
410
 
@@ -406,9 +420,9 @@ interface OnChangeTextEvent {
406
420
 
407
421
  - `value` is the new text value of the input.
408
422
 
409
- | Type | Default Value | Platform |
410
- | ---- | ------------- | -------- |
411
- | `(NativeSyntheticEvent\<OnChangeTextEvent>) => void` | - | Both |
423
+ | Type | Default Value | Platform |
424
+ |------------------------------------------------------|---------------|----------|
425
+ | `(NativeSyntheticEvent\<OnChangeTextEvent>) => void` | - | Both |
412
426
 
413
427
  #### `onEndMention`
414
428
 
@@ -416,17 +430,17 @@ Callback that is called when the user no longer edits a mention actively - has m
416
430
 
417
431
  - `indicator` is the indicator of the mention that was being edited.
418
432
 
419
- | Type | Default Value | Platform |
420
- | ---- | ------------- | -------- |
421
- | `(indicator: string) => void` | - | Both |
433
+ | Type | Default Value | Platform |
434
+ |-------------------------------|---------------|----------|
435
+ | `(indicator: string) => void` | - | Both |
422
436
 
423
437
  #### `onFocus`
424
438
 
425
439
  Callback that's called whenever the input is focused.
426
440
 
427
- | Type | Default Value | Platform |
428
- | ---- | ------------- | -------- |
429
- | `() => void` | - | Both |
441
+ | Type | Default Value | Platform |
442
+ |--------------|---------------|----------|
443
+ | `() => void` | - | Both |
430
444
 
431
445
  #### `onLinkDetected`
432
446
 
@@ -448,9 +462,9 @@ interface OnLinkDetected {
448
462
  - `start` is the starting index of the link.
449
463
  - `end` is the first index after the ending index of the link.
450
464
 
451
- | Type | Default Value | Platform |
452
- | ---- | ------------- | -------- |
453
- | `(OnLinkDetected) => void` | - | Both |
465
+ | Type | Default Value | Platform |
466
+ |----------------------------|---------------|----------|
467
+ | `(OnLinkDetected) => void` | - | Both |
454
468
 
455
469
  #### `onMentionDetected`
456
470
 
@@ -468,11 +482,11 @@ OnMentionDetected {
468
482
 
469
483
  - `text` is the mention's displayed text.
470
484
  - `indicator` is the indicator of the mention.
471
- - `attributes` are the additional user-defined attribtues that are being stored with the mention.
485
+ - `attributes` are the additional user-defined attributes that are being stored with the mention.
472
486
 
473
- | Type | Default Value | Platform |
474
- | ---- | ------------- | -------- |
475
- | `(OnMentionDetected) => void` | - | Both |
487
+ | Type | Default Value | Platform |
488
+ |-------------------------------|---------------|----------|
489
+ | `(OnMentionDetected) => void` | - | Both |
476
490
 
477
491
  #### `onStartMention`
478
492
 
@@ -480,41 +494,41 @@ Callback that gets called whenever a mention editing starts (after placing the i
480
494
 
481
495
  - `indicator` is the indicator of the mention that begins editing.
482
496
 
483
- | Type | Default Value | Platform |
484
- | ---- | ------------- | -------- |
485
- | `(indicator: string) => void` | - | Both |
497
+ | Type | Default Value | Platform |
498
+ |-------------------------------|---------------|----------|
499
+ | `(indicator: string) => void` | - | Both |
486
500
 
487
501
  #### `placeholder`
488
502
 
489
503
  The placeholder text that is displayed in the input if nothing has been typed yet. Disappears when something is typed.
490
504
 
491
- | Type | Default Value | Platform |
492
- | ---- | ------------- | -------- |
493
- | `string` | `''` | Both |
505
+ | Type | Default Value | Platform |
506
+ |----------|---------------|----------|
507
+ | `string` | `''` | Both |
494
508
 
495
509
  #### `placeholderTextColor`
496
510
 
497
511
  Input placeholder's text color.
498
512
 
499
- | Type | Default Value | Platform |
500
- | ---- | ------------- | -------- |
501
- | [`color`](https://reactnative.dev/docs/colors) | input's [color](#style) | Both |
513
+ | Type | Default Value | Platform |
514
+ |------------------------------------------------|-------------------------|----------|
515
+ | [`color`](https://reactnative.dev/docs/colors) | input's [color](#style) | Both |
502
516
 
503
517
  #### `ref`
504
518
 
505
519
  A React ref that lets you call any ref methods on the input.
506
520
 
507
- | Type | Default Value | Platform |
508
- | ---- | ------------- | -------- |
509
- | `RefObject<EnrichedTextInputInstance \| null>` | - | Both |
521
+ | Type | Default Value | Platform |
522
+ |------------------------------------------------|---------------|----------|
523
+ | `RefObject<EnrichedTextInputInstance \| null>` | - | Both |
510
524
 
511
525
  #### `selectionColor`
512
526
 
513
527
  Color of the selection rectangle that gets drawn over the selected text. On iOS, the cursor (caret) also gets set to this color.
514
528
 
515
- | Type | Default Value | Platform |
516
- | ---- | ------------- | -------- |
517
- | [`color`](https://reactnative.dev/docs/colors) | system default | Both |
529
+ | Type | Default Value | Platform |
530
+ |------------------------------------------------|----------------|----------|
531
+ | [`color`](https://reactnative.dev/docs/colors) | system default | Both |
518
532
 
519
533
  #### `style`
520
534
 
@@ -528,9 +542,9 @@ Additionally following [TextStyle](https://reactnative.dev/docs/text#style) prop
528
542
  - fontWeight
529
543
  - fontStyle only on Android
530
544
 
531
- | Type | Default Value | Platform |
532
- | ---- | ------------- | -------- |
533
- | [`View Style`](https://reactnative.dev/docs/view#style) \| [`Text Style`](https://reactnative.dev/docs/text#style) | - | Both |
545
+ | Type | Default Value | Platform |
546
+ |--------------------------------------------------------------------------------------------------------------------|---------------|----------|
547
+ | [`View Style`](https://reactnative.dev/docs/view#style) \| [`Text Style`](https://reactnative.dev/docs/text#style) | - | Both |
534
548
 
535
549
  #### `ViewProps`
536
550
 
@@ -540,9 +554,9 @@ The input inherits [ViewProps](https://reactnative.dev/docs/view#props), but kee
540
554
 
541
555
  If true, Android will use experimental synchronous events. This will prevent from input flickering when updating component size. However, this is an experimental feature, which has not been thoroughly tested. We may decide to enable it by default in a future release.
542
556
 
543
- | Type | Default Value | Platform |
544
- | ---- | ------------- | -------- |
545
- | `bool` | `false` | Android |
557
+ | Type | Default Value | Platform |
558
+ |--------|---------------|----------|
559
+ | `bool` | `false` | Android |
546
560
 
547
561
  ### Ref Methods
548
562
 
@@ -609,7 +623,7 @@ Sets the currently edited mention with a given indicator, displayed text and cus
609
623
 
610
624
  - `indicator: string` - the indicator of the set mention.
611
625
  - `text: string` - the text that should be displayed for the mention. Anything the user typed gets replaced by that text. The mention indicator isn't added to that text.
612
- - `attributes?: Record<string, string>` - additional, custom attribtues for the mention that can be passed as a typescript record. They are properly preserved through parsing from and to the HTML format.
626
+ - `attributes?: Record<string, string>` - additional, custom attributes for the mention that can be passed as a typescript record. They are properly preserved through parsing from and to the HTML format.
613
627
 
614
628
  #### `.setValue()`
615
629
 
@@ -831,7 +845,7 @@ If only a single config is given, the style applies to all mention types. You ca
831
845
 
832
846
  #### img (inline image)
833
847
 
834
- - `width` is the width of the inline image, deafults to `80`.
848
+ - `width` is the width of the inline image, defaults to `80`.
835
849
  - `height` is the height of the inline image, defaults to `80`.
836
850
 
837
851
  #### ol (ordered list)
@@ -850,12 +864,12 @@ By bullet we mean the dot that begins each line of the list.
850
864
  - `bulletColor` defines the color of the bullet, takes [color](https://reactnative.dev/docs/colors) value and defaults to `black`.
851
865
  - `bulletSize` sets both the height and the width of the bullet, defaults to `8`.
852
866
  - `marginLeft` is the margin to the left of the bullet (between the bullet and input's left edge), defaults to `16`.
853
- - `gapWidth` sets the gap between the bullet and the list item's text, deafults to `16`.
867
+ - `gapWidth` sets the gap between the bullet and the list item's text, defaults to `16`.
854
868
 
855
869
  ## Future Plans
856
870
 
857
871
  - Adding Codeblocks and Inline Images to iOS input.
858
- - Making some optimalizations around `onChangeHtml` event, maybe some imperative API to get the HTML output.
872
+ - Making some optimizations around `onChangeHtml` event, maybe some imperative API to get the HTML output.
859
873
  - Creating `EnrichedText` text component that supports our HTML output format with all additional interactions like pressing links or mentions.
860
874
  - Adding API for custom link detection regex.
861
875
  - Web library implementation via `react-native-web`.
@@ -148,7 +148,7 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
148
148
  mentionStart = start
149
149
  }
150
150
 
151
- mentionHandler.onMention(indicator, word.replaceFirst(indicator, ""))
151
+ mentionHandler.onMention(indicator, text)
152
152
  } else {
153
153
  mentionHandler.endMention()
154
154
  }
@@ -208,6 +208,11 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
208
208
  val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, spanEnd)
209
209
  spannable.setSpan(span, safeStart, safeEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
210
210
 
211
+ val hasSpaceAtTheEnd = spannable.length > safeEnd && spannable[safeEnd] == ' '
212
+ if (!hasSpaceAtTheEnd) {
213
+ spannable.insert(safeEnd, " ")
214
+ }
215
+
211
216
  view.selection.validateStyles()
212
217
  }
213
218
 
@@ -171,10 +171,11 @@
171
171
 
172
172
  for(NSNumber *activeStyle in currentActiveStyles) {
173
173
  NSInteger activeStyleBeginning = [currentActiveStylesBeginning[activeStyle] integerValue];
174
- // we end the styles that began after the currently ended style
175
- // also the ones that ended in the exact same place but are "inner" in relation to them due to StyleTypeEnum integer values
176
- // "activeStylesBeginning < i" is needed, so that we don't remove styles that have been freshly added now
177
- if((activeStyleBeginning > styleBeginning) ||
174
+
175
+ // we end the styles that began after the currently ended style but not at the "i" (cause the old style ended at exactly "i-1"
176
+ // also the ones that began in the exact same place but are "inner" in relation to them due to StyleTypeEnum integer values
177
+
178
+ if((activeStyleBeginning > styleBeginning && activeStyleBeginning < i) ||
178
179
  (activeStyleBeginning == styleBeginning && activeStyleBeginning < i && [activeStyle integerValue] > [style integerValue])) {
179
180
  [fixedEndedStyles addObject:activeStyle];
180
181
  [stylesToBeReAdded addObject:activeStyle];
@@ -405,24 +406,16 @@
405
406
  if(html.length >= 13) {
406
407
  NSString *firstSix = [html substringWithRange:NSMakeRange(0, 6)];
407
408
  NSString *lastSeven = [html substringWithRange:NSMakeRange(html.length-7, 7)];
408
- NSInteger newlinesCount = [[html componentsSeparatedByString:@"\n"] count] - 1;
409
409
 
410
410
  if([firstSix isEqualToString:@"<html>"] && [lastSeven isEqualToString:@"</html>"]) {
411
- if(newlinesCount >= 2) {
412
- // looks like our format
413
- // we want to get the string without <html> and </html> and their newlines
414
- // so we skip first 7 characters and get the string 7+8 = 15 characters shorter
415
- fixedHtml = [html substringWithRange: NSMakeRange(7, html.length - 15)];
416
- } else {
417
- // most likely a valid html but with some newline differences
418
- fixedHtml = [html copy];
419
- // firstly remove newlined html tags if any:
420
- fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<html>\n" withString:@""];
421
- fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"\n</html>" withString:@""];
422
- // fallback; remove html tags without their newlines
423
- fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<html>" withString:@""];
424
- fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"</html>" withString:@""];
425
- }
411
+ // remove html tags, might be with newlines or without them
412
+ fixedHtml = [html copy];
413
+ // firstly remove newlined html tags if any:
414
+ fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<html>\n" withString:@""];
415
+ fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"\n</html>" withString:@""];
416
+ // fallback; remove html tags without their newlines
417
+ fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<html>" withString:@""];
418
+ fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"</html>" withString:@""];
426
419
  } else {
427
420
  // in other case we are most likely working with some external html - try getting the styles from between body tags
428
421
  NSRange openingBodyRange = [html rangeOfString:@"<body>"];
@@ -438,38 +431,35 @@
438
431
 
439
432
  // second processing - try fixing htmls with wrong newlines' setup
440
433
  if(fixedHtml != nullptr) {
441
- NSInteger newlinesCount = [[fixedHtml componentsSeparatedByString:@"/n"] count] - 1;
442
- if(newlinesCount == 0) {
443
- // add <br> tag wherever needed
444
- fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<p></p>" withString:@"<br>"];
445
-
446
- // remove <p> tags inside of <li>
447
- fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<li><p>" withString:@"<li>"];
448
- fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"</p></li>" withString:@"</li>"];
449
-
450
- // tags that have to be in separate lines
451
- fixedHtml = [self stringByAddingNewlinesToTag:@"<br>" inString:fixedHtml leading:YES trailing:YES];
452
- fixedHtml = [self stringByAddingNewlinesToTag:@"<ul>" inString:fixedHtml leading:YES trailing:YES];
453
- fixedHtml = [self stringByAddingNewlinesToTag:@"</ul>" inString:fixedHtml leading:YES trailing:YES];
454
- fixedHtml = [self stringByAddingNewlinesToTag:@"<ol>" inString:fixedHtml leading:YES trailing:YES];
455
- fixedHtml = [self stringByAddingNewlinesToTag:@"</ol>" inString:fixedHtml leading:YES trailing:YES];
456
- fixedHtml = [self stringByAddingNewlinesToTag:@"<blockquote>" inString:fixedHtml leading:YES trailing:YES];
457
- fixedHtml = [self stringByAddingNewlinesToTag:@"</blockquote>" inString:fixedHtml leading:YES trailing:YES];
458
-
459
- // line opening tags
460
- fixedHtml = [self stringByAddingNewlinesToTag:@"<p>" inString:fixedHtml leading:YES trailing:NO];
461
- fixedHtml = [self stringByAddingNewlinesToTag:@"<li>" inString:fixedHtml leading:YES trailing:NO];
462
- fixedHtml = [self stringByAddingNewlinesToTag:@"<h1>" inString:fixedHtml leading:YES trailing:NO];
463
- fixedHtml = [self stringByAddingNewlinesToTag:@"<h2>" inString:fixedHtml leading:YES trailing:NO];
464
- fixedHtml = [self stringByAddingNewlinesToTag:@"<h3>" inString:fixedHtml leading:YES trailing:NO];
465
-
466
- // line closing tags
467
- fixedHtml = [self stringByAddingNewlinesToTag:@"</p>" inString:fixedHtml leading:NO trailing:YES];
468
- fixedHtml = [self stringByAddingNewlinesToTag:@"</li>" inString:fixedHtml leading:NO trailing:YES];
469
- fixedHtml = [self stringByAddingNewlinesToTag:@"</h1>" inString:fixedHtml leading:NO trailing:YES];
470
- fixedHtml = [self stringByAddingNewlinesToTag:@"</h2>" inString:fixedHtml leading:NO trailing:YES];
471
- fixedHtml = [self stringByAddingNewlinesToTag:@"</h3>" inString:fixedHtml leading:NO trailing:YES];
472
- }
434
+ // add <br> tag wherever needed
435
+ fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<p></p>" withString:@"<br>"];
436
+
437
+ // remove <p> tags inside of <li>
438
+ fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"<li><p>" withString:@"<li>"];
439
+ fixedHtml = [fixedHtml stringByReplacingOccurrencesOfString:@"</p></li>" withString:@"</li>"];
440
+
441
+ // tags that have to be in separate lines
442
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<br>" inString:fixedHtml leading:YES trailing:YES];
443
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<ul>" inString:fixedHtml leading:YES trailing:YES];
444
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</ul>" inString:fixedHtml leading:YES trailing:YES];
445
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<ol>" inString:fixedHtml leading:YES trailing:YES];
446
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</ol>" inString:fixedHtml leading:YES trailing:YES];
447
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<blockquote>" inString:fixedHtml leading:YES trailing:YES];
448
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</blockquote>" inString:fixedHtml leading:YES trailing:YES];
449
+
450
+ // line opening tags
451
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<p>" inString:fixedHtml leading:YES trailing:NO];
452
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<li>" inString:fixedHtml leading:YES trailing:NO];
453
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<h1>" inString:fixedHtml leading:YES trailing:NO];
454
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<h2>" inString:fixedHtml leading:YES trailing:NO];
455
+ fixedHtml = [self stringByAddingNewlinesToTag:@"<h3>" inString:fixedHtml leading:YES trailing:NO];
456
+
457
+ // line closing tags
458
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</p>" inString:fixedHtml leading:NO trailing:YES];
459
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</li>" inString:fixedHtml leading:NO trailing:YES];
460
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</h1>" inString:fixedHtml leading:NO trailing:YES];
461
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</h2>" inString:fixedHtml leading:NO trailing:YES];
462
+ fixedHtml = [self stringByAddingNewlinesToTag:@"</h3>" inString:fixedHtml leading:NO trailing:YES];
473
463
  }
474
464
 
475
465
  return fixedHtml;
@@ -76,7 +76,7 @@
76
76
 
77
77
  - (void)tryHandlingPlainTextItemsIn:(UIPasteboard *)pasteboard range:(NSRange)range input:(EnrichedTextInputView *)input {
78
78
  NSArray *existingTypes = pasteboard.pasteboardTypes;
79
- NSArray *handledTypes = @[UTTypeUTF8PlainText.identifier, UTTypePlainText.identifier];
79
+ NSArray *handledTypes = @[UTTypeUTF8PlainText.identifier, UTTypePlainText.identifier, UTTypeURL.identifier];
80
80
  NSString *plainText;
81
81
 
82
82
  for(NSString *type in handledTypes) {
@@ -90,6 +90,8 @@
90
90
  plainText = [[NSString alloc]initWithData:value encoding:NSUTF8StringEncoding];
91
91
  } else if([value isKindOfClass:[NSString class]]) {
92
92
  plainText = (NSString *)value;
93
+ } else if([value isKindOfClass:[NSURL class]]) {
94
+ plainText = [(NSURL *)value absoluteString];
93
95
  }
94
96
  }
95
97
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-enriched",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Rich Text Editor component for React Native",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
@@ -48,14 +48,14 @@
48
48
  ],
49
49
  "repository": {
50
50
  "type": "git",
51
- "url": "git+https://github.com/software-mansion-labs/react-native-rich-text-editor.git"
51
+ "url": "git+https://github.com/software-mansion-labs/react-native-enriched.git"
52
52
  },
53
53
  "author": "Software Mansion <contact@swmansion.com> (https://swmansion.com)",
54
54
  "license": "MIT",
55
55
  "bugs": {
56
- "url": "https://github.com/software-mansion-labs/react-native-rich-text-editor/issues"
56
+ "url": "https://github.com/software-mansion-labs/react-native-enriched/issues"
57
57
  },
58
- "homepage": "https://github.com/software-mansion-labs/react-native-rich-text-editor#readme",
58
+ "homepage": "https://github.com/software-mansion-labs/react-native-enriched#readme",
59
59
  "publishConfig": {
60
60
  "registry": "https://registry.npmjs.org/"
61
61
  },