schlechtenburg/packages/rich-text/README.md

491 lines
15 KiB
Markdown
Raw Normal View History

2024-10-08 07:15:26 +00:00
# Rich Text
This module contains helper functions to convert HTML or a DOM tree into a rich text value and back, and to modify the value with functions that are similar to `String` methods, plus some additional ones for formatting.
## Installation
Install the module
```bash
npm install @wordpress/rich-text
```
_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._
## Usage
The Rich Text package is designed to aid in the manipulation of plain text strings in order that they can represent complex formatting.
By using a `RichTextValue` value object (referred to from here on as `value`) it is possible to separate text from formatting, thereby affording the ability to easily search and manipulate rich formats.
Examples of rich formats include:
- bold, italic, superscript (etc)
- links
- unordered/ordered lists
### The RichTextValue object
The value object is comprised of the following:
- `text` - the string of text to which rich formats are to be applied.
- `formats` - a sparse array of the same length as `text` that is filled with [formats](https://developer.wordpress.org/block-editor/how-to-guides/format-api/) (e.g. `core/link`, `core/bold` etc.) at the positions where the text is formatted.
- `start` - an index in the `text` representing the _start_ of the currently active selection.
- `end` - an index in the `text` representing the _end_ of the currently active selection.
You should not attempt to create your own `value` objects. Rather you should rely on the built in methods of the `@wordpress/rich-text` package to build these for you.
It is important to understand how a value represents richly formatted text. Here is an example to illustrate.
If `text` is formatted from position 2-5 in bold (`core/bold`) and from position 2-8 with a link (`core/link`), then you'll find:
- arrays within the sparse array at positions 2-5 that include the `core/bold` format
- arrays within the sparse array at positions 2-8 that include the `core/link` format
Here's how that would look:
```js
{
text: 'Hello world', // length 11
formats: [
[], // 0
[],
[ // 2
{
type: 'core/bold',
},
{
type: 'core/link',
}
],
[
{
type: 'core/bold',
},
{
type: 'core/link',
}
],
[
{
type: 'core/bold',
},
{
type: 'core/link',
}
],
[
{
type: 'core/bold',
},
{
type: 'core/link',
}
],
[ // 6
{
type: 'core/link',
}
]
[
{
type: 'core/link',
}
],
[
{
type: 'core/link',
}
],
[], // 9
[], // 10
[], // 11
]
}
```
### Selections
Let's continue to consider the above example with the text `Hello world`.
If, as a user, I make a selection of the word `Hello` this would result in a value object with `start` and `end` as `0` and `5` respectively.
In general, this is useful for knowing which portion of the text is selected. However, we need to consider that selections may also be "collapsed".
#### Collapsed selections
A collapsed selection is one where `start` and `end` values are _identical_ (e.g. `start: 4, end: 4`). This happens when no characters are selected, but there is a caret present. This most often occurs when a user places the cursor/caret within a string of text but does not make a selection.
Given that the selection has no "range" (i.e. there is no difference between `start` and `end` indices), finding the currently selected portion of text from collapsed values can be challenging.
## API
<!-- START TOKEN(Autogenerated API docs) -->
### applyFormat
Apply a format object to a Rich Text value from the given `startIndex` to the given `endIndex`. Indices are retrieved from the selection if none are provided.
_Parameters_
- _value_ `RichTextValue`: Value to modify.
- _format_ `RichTextFormat`: Format to apply.
- _startIndex_ `[number]`: Start index.
- _endIndex_ `[number]`: End index.
_Returns_
- `RichTextValue`: A new value with the format applied.
### concat
Combine all Rich Text values into one. This is similar to `String.prototype.concat`.
_Parameters_
- _values_ `...RichTextValue`: Objects to combine.
_Returns_
- `RichTextValue`: A new value combining all given records.
### create
Create a RichText value from an `Element` tree (DOM), an HTML string or a plain text string, with optionally a `Range` object to set the selection. If called without any input, an empty value will be created. The optional functions can be used to filter out content.
A value will have the following shape, which you are strongly encouraged not to modify without the use of helper functions:
```js
{
text: string,
formats: Array,
replacements: Array,
?start: number,
?end: number,
}
```
As you can see, text and formatting are separated. `text` holds the text, including any replacement characters for objects and lines. `formats`, `objects` and `lines` are all sparse arrays of the same length as `text`. It holds information about the formatting at the relevant text indices. Finally `start` and `end` state which text indices are selected. They are only provided if a `Range` was given.
_Parameters_
- _$1_ `[Object]`: Optional named arguments.
- _$1.element_ `[Element]`: Element to create value from.
- _$1.text_ `[string]`: Text to create value from.
- _$1.html_ `[string]`: HTML to create value from.
- _$1.range_ `[Range]`: Range to create value from.
- _$1.\_\_unstableIsEditableTree_ `[boolean]`:
_Returns_
- `RichTextValue`: A rich text value.
### getActiveFormat
Gets the format object by type at the start of the selection. This can be used to get e.g. the URL of a link format at the current selection, but also to check if a format is active at the selection. Returns undefined if there is no format at the selection.
_Parameters_
- _value_ `RichTextValue`: Value to inspect.
- _formatType_ `string`: Format type to look for.
_Returns_
- `RichTextFormat|undefined`: Active format object of the specified type, or undefined.
### getActiveFormats
Gets the all format objects at the start of the selection.
_Parameters_
- _value_ `RichTextValue`: Value to inspect.
- _EMPTY_ACTIVE_FORMATS_ `Array`: Array to return if there are no active formats.
_Returns_
- `RichTextFormatList`: Active format objects.
### getActiveObject
Gets the active object, if there is any.
_Parameters_
- _value_ `RichTextValue`: Value to inspect.
_Returns_
- `RichTextFormat|void`: Active object, or undefined.
### getTextContent
Get the textual content of a Rich Text value. This is similar to `Element.textContent`.
_Parameters_
- _value_ `RichTextValue`: Value to use.
_Returns_
- `string`: The text content.
### insert
Insert a Rich Text value, an HTML string, or a plain text string, into a Rich Text value at the given `startIndex`. Any content between `startIndex` and `endIndex` will be removed. Indices are retrieved from the selection if none are provided.
_Parameters_
- _value_ `RichTextValue`: Value to modify.
- _valueToInsert_ `RichTextValue|string`: Value to insert.
- _startIndex_ `[number]`: Start index.
- _endIndex_ `[number]`: End index.
_Returns_
- `RichTextValue`: A new value with the value inserted.
### insertObject
Insert a format as an object into a Rich Text value at the given `startIndex`. Any content between `startIndex` and `endIndex` will be removed. Indices are retrieved from the selection if none are provided.
_Parameters_
- _value_ `RichTextValue`: Value to modify.
- _formatToInsert_ `RichTextFormat`: Format to insert as object.
- _startIndex_ `[number]`: Start index.
- _endIndex_ `[number]`: End index.
_Returns_
- `RichTextValue`: A new value with the object inserted.
### isCollapsed
Check if the selection of a Rich Text value is collapsed or not. Collapsed means that no characters are selected, but there is a caret present. If there is no selection, `undefined` will be returned. This is similar to `window.getSelection().isCollapsed()`.
_Parameters_
- _props_ `RichTextValue`: The rich text value to check.
- _props.start_ `RichTextValue[ 'start' ]`:
- _props.end_ `RichTextValue[ 'end' ]`:
_Returns_
- `boolean | undefined`: True if the selection is collapsed, false if not, undefined if there is no selection.
### isEmpty
Check if a Rich Text value is Empty, meaning it contains no text or any objects (such as images).
_Parameters_
- _value_ `RichTextValue`: Value to use.
_Returns_
- `boolean`: True if the value is empty, false if not.
### join
Combine an array of Rich Text values into one, optionally separated by `separator`, which can be a Rich Text value, HTML string, or plain text string. This is similar to `Array.prototype.join`.
_Parameters_
- _values_ `Array<RichTextValue>`: An array of values to join.
- _separator_ `[string|RichTextValue]`: Separator string or value.
_Returns_
- `RichTextValue`: A new combined value.
### registerFormatType
Registers a new format provided a unique name and an object defining its behavior.
_Parameters_
- _name_ `string`: Format name.
- _settings_ `WPFormat`: Format settings.
_Returns_
- `WPFormat|undefined`: The format, if it has been successfully registered; otherwise `undefined`.
### remove
Remove content from a Rich Text value between the given `startIndex` and `endIndex`. Indices are retrieved from the selection if none are provided.
_Parameters_
- _value_ `RichTextValue`: Value to modify.
- _startIndex_ `[number]`: Start index.
- _endIndex_ `[number]`: End index.
_Returns_
- `RichTextValue`: A new value with the content removed.
### removeFormat
Remove any format object from a Rich Text value by type from the given `startIndex` to the given `endIndex`. Indices are retrieved from the selection if none are provided.
_Parameters_
- _value_ `RichTextValue`: Value to modify.
- _formatType_ `string`: Format type to remove.
- _startIndex_ `[number]`: Start index.
- _endIndex_ `[number]`: End index.
_Returns_
- `RichTextValue`: A new value with the format applied.
### replace
Search a Rich Text value and replace the match(es) with `replacement`. This is similar to `String.prototype.replace`.
_Parameters_
- _value_ `RichTextValue`: The value to modify.
- _pattern_ `RegExp|string`: A RegExp object or literal. Can also be a string. It is treated as a verbatim string and is not interpreted as a regular expression. Only the first occurrence will be replaced.
- _replacement_ `Function|string`: The match or matches are replaced with the specified or the value returned by the specified function.
_Returns_
- `RichTextValue`: A new value with replacements applied.
### RichTextData
The RichTextData class is used to instantiate a wrapper around rich text values, with methods that can be used to transform or manipulate the data.
- Create an empty instance: `new RichTextData()`.
- Create one from an HTML string: `RichTextData.fromHTMLString(
'<em>hello</em>' )`.
- Create one from a wrapper HTMLElement: `RichTextData.fromHTMLElement(
document.querySelector( 'p' ) )`.
- Create one from plain text: `RichTextData.fromPlainText( '1\n2' )`.
- Create one from a rich text value: `new RichTextData( { text: '...',
formats: [ ... ] } )`.
### RichTextValue
An object which represents a formatted string. See main `@wordpress/rich-text` documentation for more information.
### slice
Slice a Rich Text value from `startIndex` to `endIndex`. Indices are retrieved from the selection if none are provided. This is similar to `String.prototype.slice`.
_Parameters_
- _value_ `RichTextValue`: Value to modify.
- _startIndex_ `[number]`: Start index.
- _endIndex_ `[number]`: End index.
_Returns_
- `RichTextValue`: A new extracted value.
### split
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.
_Parameters_
- _value_ `RichTextValue`:
- _string_ `[number|string]`: Start index, or string at which to split.
_Returns_
- `Array<RichTextValue>|undefined`: An array of new values.
### store
Store definition for the rich-text namespace.
_Related_
- <https://github.com/WordPress/gutenberg/blob/HEAD/packages/data/README.md#createReduxStore>
_Type_
- `Object`
### toggleFormat
Toggles a format object to a Rich Text value at the current selection.
_Parameters_
- _value_ `RichTextValue`: Value to modify.
- _format_ `RichTextFormat`: Format to apply or remove.
_Returns_
- `RichTextValue`: A new value with the format applied or removed.
### toHTMLString
Create an HTML string from a Rich Text value.
_Parameters_
- _$1_ `Object`: Named arguments.
- _$1.value_ `RichTextValue`: Rich text value.
- _$1.preserveWhiteSpace_ `[boolean]`: Preserves newlines if true.
_Returns_
- `string`: HTML string.
### unregisterFormatType
Unregisters a format.
_Parameters_
- _name_ `string`: Format name.
_Returns_
- `WPFormat|undefined`: The previous format value, if it has been successfully unregistered; otherwise `undefined`.
### useAnchor
This hook, to be used in a format type's Edit component, returns the active element that is formatted, or a virtual element for the selection range if no format is active. The returned value is meant to be used for positioning UI, e.g. by passing it to the `Popover` component via the `anchor` prop.
_Parameters_
- _$1_ `Object`: Named parameters.
- _$1.editableContentElement_ `HTMLElement|null`: The element containing the editable content.
- _$1.settings_ `WPFormat=`: The format type's settings.
_Returns_
- `Element|VirtualAnchorElement|undefined|null`: The active element or selection range.
### useAnchorRef
This hook, to be used in a format type's Edit component, returns the active element that is formatted, or the selection range if no format is active. The returned value is meant to be used for positioning UI, e.g. by passing it to the `Popover` component.
_Parameters_
- _$1_ `Object`: Named parameters.
- _$1.ref_ `RefObject<HTMLElement>`: React ref of the element containing the editable content.
- _$1.value_ `RichTextValue`: Value to check for selection.
- _$1.settings_ `WPFormat`: The format type's settings.
_Returns_
- `Element|Range`: The active element or selection range.
<!-- END TOKEN(Autogenerated API docs) -->
## Contributing to this package
This is an individual package that's part of the Gutenberg project. The project is organized as a monorepo. It's made up of multiple self-contained software packages, each with a specific purpose. The packages in this monorepo are published to [npm](https://www.npmjs.com/) and used by [WordPress](https://make.wordpress.org/core/) as well as other software projects.
To find out more about contributing to this package or Gutenberg as a whole, please read the project's main [contributor guide](https://github.com/WordPress/gutenberg/tree/HEAD/CONTRIBUTING.md).
<br /><br /><p align="center"><img src="https://s.w.org/style/images/codeispoetry.png?1" alt="Code is Poetry." /></p>