rich-content-preview
#
IntroductionThe Preview project comes to meet the requirement for a brief content preview; similar concept could be found in social media applications.
#
ArchitectureThe core idea is to transform the content state and to display it within RichContentViewer
. This transformation is a product of content state metadata and a set of rules defined by the consumer. This section discusses the main logic elements required to perform such a transformation.
#
Content State AnalyzerThe content state analyzer retrieves content metadata containing the info regarding the data rather draft block and entity structure.
For example, the metadata could provide the following details:
- number of images and videos
- length of text (in total and per block)
- lists and code-blocks consisting of multiple sequential blocks are retrieved as a whole
#
Content State BuilderThe content state builder provides a way to create a preview content state using the retrieved metadata. The preview state then can be rendered by RichContentViewer
.
#
Rule EngineThe rule engine provides a way to define transformation rules and to apply them on a given ContentState
according to the metadata.
#
Transformation RuleThe transformation rule consists of condition and transform action.
Example:
#
Preview InteractionsThe preview interactions allow to expand hidden content. The rich-content
repo introduces 3 predefined interactions. The Content State Builder exposes methods to add interactions to the preview state, and the RichContentViewer
renders the interaction components.
#
'Read More'The Read More
interacton relies on react-lines-ellipsis package. It displays required number of lines appended by an ellipsis. Although the package is capable to handle the HTML content, this feature is experimental. The current interacton is limited to work with plain text only. Mouse click expands the full post.
#
'See Full Post'The See Full Post
displays a text label over an overlay. Mouse click expands the full post.
#
Image CounterThe Image Counter
renders hidden image counter. By default, the counter label placed above the last visible image element. The image elements are selected by role='img'
attribute.
#
APIs#
getContentStateMetadataThe metadata is derived from ContentState and exposes its details:
These details are categorized by content type rather actual ContentState structure.
#
ContentStateMetadata.allTextThe ContentStateMetadata.allText
exposes all the textual content a string array.
#
ContentStateMetadata.plainThe ContentStateMetadata.plain
exposes the textual content extracted from the unstyled
blocks as a string array.
#
ContentStateMetadata.olThe ContentStateMetadata.ol
exposes the textual content extracted from the ordered list blocks as a string array.
#
ContentStateMetadata.ulThe ContentStateMetadata.ul
exposes the textual content extracted from the unordered list blocks as a string array.
#
ContentStateMetadata.quotesThe ContentStateMetadata.quotes
exposes the textual content extracted from the blockquote
blocks as a string array.
#
ContentStateMetadata.codeThe ContentStateMetadata.code
exposes the textual content extracted from the code-block
blocks as a string array.
#
ContentStateMetadata.h1/h2/h3/h4/h5/h6The ContentStateMetadata.h1/h2/h3/h4/h5/h6
exposes the textual content extracted from the heading blocks as a string array.
#
ContentStateMetadata.imagesThe ContentStateMetadata.images
exposes the data extracted from image
/ gallery
/ giphy
entities.
The image data object structure is:
The properties marked with ?
are optional and relevant only for some of the image entities.
#
ContentStateMetadata.videosThe ContentStateMetadata.videos
exposes the data extracted from video
/ sound-cloud
/ youtube
entities.
The video data object structure is:
#
ContentStateMetadata.filesThe ContentStateMetadata.files
exposes the data extracted from file-upload
entities.
The file object structure:
#
ContentStateMetadata.mapsThe ContentStateMetadata.maps
exposes the data extracted from google-map
entities. The map data structure is similar to mapSettings
object structure (found in the map entity data).
#
ContentStateBuilderThe ContentStateBuilder
exposes API for ContentState generation, based on the Builder design pattern.
#
Content generation methodsThe basic ContentStateBuilder
methods allow to add content elements to the constructed ContentState. The methods named after the content type being added, e.g. is image
method allows to add an image, and plain
method adds plain text. The methods could be chained:
#
ContentStateBuilder.plain(text, config)The ContentStateBuilder.plain
method appends an unstyled
block with given text
. If the text
param is a string array, then it will append block for each string. The optional config
is merged to the block data.
#
ContentStateBuilder.ul(text, config)The ContentStateBuilder.ul
method appends an unordered-list-item
block with given text
. If the text
param is a string array, then it will append block for each string. The optional config
is merged to the block data.
#
ContentStateBuilder.ol(text, config)The ContentStateBuilder.ol
method appends an ordered-list-item
block with given text
. If the text
param is a string array, then it will append block for each string. The optional config
is merged to the block data.
#
ContentStateBuilder.code(text, config)The ContentStateBuilder.code
method appends a code-block
block with given text
. If the text
param is a string array, then it will append block for each string. The optional config
is merged to the block data.
#
ContentStateBuilder.quote(text, config)The ContentStateBuilder.quote
method appends a blockquote
block with given text
. If the text
param is a string array, then it will append block for each string. The optional config
is merged to the block data.
#
ContentStateBuilder.h1/h2/h3/h4/h5/h6(text, config)The ContentStateBuilder.h1/h2/h3/h4/h5/h6
methods append a header block with given text
. If the text
param is a string array, then it will append block for each string. The optional config
is merged to the block data.
#
ContentStateBuilder.image({ mediaInfo, config, overrides })The ContentStateBuilder.image
method appends an atomic
block to the blocks
and a wix-draft-plugin-image
entity to the entityMap
. The optional params config
and overrides
are merged with the entity.data.config
and entity.data
, respectively.
The mediaInfo
param is expected to be an image data object returned by ContentStateMetadata.images method.
#
ContentStateBuilder.giphy({ mediaInfo, config, overrides })The ContentStateBuilder.giphy
method appends an atomic
block to the blocks
and a wix-draft-plugin-giphy
entity to the entityMap
. The optional params config
and overrides
are merged with the entity.data.config
and entity.data
, respectively.
The mediaInfo
param is expected to be an image data object returned by ContentStateMetadata.images method.
#
ContentStateBuilder.gallery({ mediaInfo, config, overrides })The ContentStateBuilder.gallery
method appends an atomic
block to the blocks
and a wix-draft-plugin-gallery
entity to the entityMap
. The optional params config
and overrides
are merged with the entity.data.config
and entity.data
, respectively.
The items
param is expected to be an array of image data objects returned by ContentStateMetadata.images method.
#
ContentStateBuilder.video({ mediaInfo, config, overrides })The ContentStateBuilder.video
method appends an atomic
block to the blocks
and a wix-draft-plugin-video
entity to the entityMap
. The optional params config
and overrides
are merged with the entity.data.config
and entity.data
, respectively.
The mediaInfo
param is expected to be a video data object returned by ContentStateMetadata.videos method.
#
ContentStateBuilder.soundCloud({ mediaInfo, config, overrides })The ContentStateBuilder.soundCloud
method appends an atomic
block to the blocks
and a wix-draft-plugin-sound-cloud
entity to the entityMap
. The optional params config
and overrides
are merged with the entity.data.config
and entity.data
, respectively.
The mediaInfo
param is expected to be a video data object returned by ContentStateMetadata.videos method.
#
ContentStateBuilder.file({ mediaInfo, config, overrides })The ContentStateBuilder.file
method appends an atomic
block to the blocks
and a wix-draft-plugin-file-upload
entity to the entityMap
. The optional params config
and overrides
are merged with the entity.data.config
and entity.data
, respectively.
The mediaInfo
param is expected to be a file data object returned by ContentStateMetadata.files method.
#
ContentStateBuilder.map({ mediaInfo, config, overrides })The ContentStateBuilder.map
method appends an atomic
block to the blocks
and a wix-draft-plugin-map
entity to the entityMap
. The optional params config
and overrides
are merged with the entity.data.config
and entity.data
, respectively.
The mediaInfo
parameter is expected to be a map data object returned by ContentStateMetadata.maps method.
#
ContentStateTransformationThe ContentStateTransformation
represents a rule to be applied on content state in order to achieve the desired preview state:
In the code fragment above, the _if
and _then
arguments are functions following the convention:
The optional argument initialPreviewState
allows to pass an initial preview state.
The following fragment demonstrates the "if content images > 3 => add a gallery with 3 items" rule definition:
The rule
method allows to chain multiple rules. They will be applied one after another:
#
Content InteractionsThe content interaction indicate that the preview content is collapsed, and provide a way to expand it. Content interactions work at the block level. Every interaction consists of the following elements:
ContentStateBuilder API allows a consumer to add an interaction to the preview state and configure it. These APIs can be chained just like any other ContentStateBuilder method:
In this example, the
readMore
interaction is being applied to the previousplain
block.block data interactions array contains configuration data for all the interactions applied to the block
UI component defines the appearance of the interaction element
#
Predefined Interactions#
ReadMoreThe ReadMore
component comes to display a portion of a long text, appending it an ellipsis symbol (…
) and label (by default, those are '… read more').
The ContentStateBuilder exposes readMore
API that accepts configuration object:
The text
field allows to specify the text to be displayed. By default, the text is taken from the wrapped children.
The onClick
field is common for all the interactions. It defines the interaction click behavior, by intercepting the expansion click.
#
SeeFullPostThe SeeFullPost
interaction adds an overlay containing a link-like label (by default, it says See Full Post
). The click on label expands the full content. The settings object:
The ContentStateBuilder
exposes seeFullPost
method that applies the interaction on the previous block data.
#
ImageCounterThe ImageCounter
serves as a counter of media entities in collapsed content. The configuration object structure:
The counter
field is self-explanatory, the formatLabel
defines the format of the label. The default implementation is:
The imageSelector
function selects images that should be decorated by the counter label, among the images found within ImageCounter
children. By default, last image is selected.
The ContentStateBuilder
exposes imageCounter
method that applies the interaction on previous block data.
#
RichContentViewer IntegrationRichContentViewer config
prop now allows to pass the preview related configuration, by adding the following entry:
The contentInteractionMappers
field allows to pass the interactions as a function array, similar to the typeMappers
and inlineStyleMappers
. The preview
package exports the interactionMap
API containing three predefined interactions mentioned in previous section.
The onPreviewExpand
handler determines the behavior on content expansion. The RichContentPreview
component wraps the RichContentViewer
while providing the default PREVIEW
configuration, interaction map, and default transformation rule:
The default rule displays 3 lines of plain text, and a single image appended by 'See Full Post' label, if the ContentState contains less than 5 images; otherwise, it displays a gallery grid of 4 images with image counter.
#
Custom InteractionsTBD