-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
update-formats.js
53 lines (46 loc) · 1.57 KB
/
update-formats.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* Internal dependencies
*/
import { isFormatEqual } from './is-format-equal';
/** @typedef {import('./types').RichTextValue} RichTextValue */
/**
* Efficiently updates all the formats from `start` (including) until `end`
* (excluding) with the active formats. Mutates `value`.
*
* @param {Object} $1 Named paramentes.
* @param {RichTextValue} $1.value Value te update.
* @param {number} $1.start Index to update from.
* @param {number} $1.end Index to update until.
* @param {Array} $1.formats Replacement formats.
*
* @return {RichTextValue} Mutated value.
*/
export function updateFormats( { value, start, end, formats } ) {
// Start and end may be switched in case of delete.
const min = Math.min( start, end );
const max = Math.max( start, end );
const formatsBefore = value.formats[ min - 1 ] || [];
const formatsAfter = value.formats[ max ] || [];
// First, fix the references. If any format right before or after are
// equal, the replacement format should use the same reference.
value.activeFormats = formats.map( ( format, index ) => {
if ( formatsBefore[ index ] ) {
if ( isFormatEqual( format, formatsBefore[ index ] ) ) {
return formatsBefore[ index ];
}
} else if ( formatsAfter[ index ] ) {
if ( isFormatEqual( format, formatsAfter[ index ] ) ) {
return formatsAfter[ index ];
}
}
return format;
} );
while ( --end >= start ) {
if ( value.activeFormats.length > 0 ) {
value.formats[ end ] = value.activeFormats;
} else {
delete value.formats[ end ];
}
}
return value;
}