83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
/**
|
|
* Internal dependencies
|
|
*/
|
|
|
|
import { RichTextValue } from "./types";
|
|
|
|
/** @typedef {import('./types').RichTextValue} RichTextValue */
|
|
|
|
/**
|
|
* Split a Rich Text value in two at the given `startIndex` and `endIndex`, or
|
|
* split at the given separator. This is similar to `String.prototype.split`.
|
|
* Indices are retrieved from the selection if none are provided.
|
|
*
|
|
* @param {RichTextValue} value
|
|
* @param {number|string} [string] Start index, or string at which to split.
|
|
*
|
|
* @return {Array<RichTextValue>|undefined} An array of new values.
|
|
*/
|
|
export function split( value: RichTextValue, string: number|string, endIndex?: number): RichTextValue[]|undefined {
|
|
if ( typeof string !== 'string' ) {
|
|
return splitAtSelection(value, string, endIndex);
|
|
}
|
|
|
|
const { formats, replacements, text, start, end } = value;
|
|
|
|
let nextStart = 0;
|
|
|
|
return text.split( string ).map( ( substring ) => {
|
|
const startIndex = nextStart;
|
|
const value: RichTextValue = {
|
|
formats: formats.slice( startIndex, startIndex + substring.length ),
|
|
replacements: replacements.slice(
|
|
startIndex,
|
|
startIndex + substring.length
|
|
),
|
|
text: substring,
|
|
};
|
|
|
|
nextStart += string.length + substring.length;
|
|
|
|
if ( start !== undefined && end !== undefined ) {
|
|
if ( start >= startIndex && start < nextStart ) {
|
|
value.start = start - startIndex;
|
|
} else if ( start < startIndex && end > startIndex ) {
|
|
value.start = 0;
|
|
}
|
|
|
|
if ( end >= startIndex && end < nextStart ) {
|
|
value.end = end - startIndex;
|
|
} else if ( start < nextStart && end > nextStart ) {
|
|
value.end = substring.length;
|
|
}
|
|
}
|
|
|
|
return value;
|
|
} );
|
|
}
|
|
|
|
function splitAtSelection(
|
|
{ formats, replacements, text, start, end }: RichTextValue,
|
|
startIndex: number|undefined = start,
|
|
endIndex: number|undefined = end
|
|
): RichTextValue[]|undefined {
|
|
if ( start === undefined || end === undefined ) {
|
|
return;
|
|
}
|
|
|
|
const before = {
|
|
formats: formats.slice( 0, startIndex ),
|
|
replacements: replacements.slice( 0, startIndex ),
|
|
text: text.slice( 0, startIndex ),
|
|
};
|
|
const after = {
|
|
formats: formats.slice( endIndex ),
|
|
replacements: replacements.slice( endIndex ),
|
|
text: text.slice( endIndex ),
|
|
start: 0,
|
|
end: 0,
|
|
};
|
|
|
|
return [ before, after ];
|
|
}
|