Renderer

Typescript โค๏ธ

Renderer component

Install
yarn add @atlaskit/renderer
Source
Bundle
Changelog
Latest

113.2.2

Patch Changes

  • Updated dependencies

Note: This component is designed for internal Atlassian development.

External contributors will be able to use this component but will not be able to submit issues.

This component provides a renderer for ADF documents.

Usage

Use the component in your React app as follows:

import { ReactRenderer } from '@atlaskit/renderer'; ReactDOM.render(<ReactRenderer document={DOCUMENT} />, container);

Example

With Providers

Input
<Renderer>

Hello, World! Look I can do italic , strong and underlined text! and action mark and invalid action mark

My favourite emoji are . What are yours?

 

Hi, my name is... My name is... My name is... My name is :D

This is a . And this is a broken

Mention with restricted access

Mentions with generic ids

This is a text with multiple spaces and tabs.

italiclinkstrike-throughstrongsubsupunderline red text

some inline code: const foo = bar();

fallback text in node.attrs.text
fallback text in node.text
[very unknown]

This is text content inside unknown block
This is also a piece of text inside unknown block
Madness?
This is
Sparta!

This is a line with
a hardbreak in it.

Showing a status:

Paragraph with 1 level of indentation

Paragraph with 2 levels of indentation

Paragraph with 3 levels of indentation

Paragraph with 4 levels of indentation

Paragraph with 5 levels of indentation

Paragraph with 6 levels of indentation

Paragraph with center alignment

Paragraph with end alignment

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

Heading 1 with 1 level of indentation

Heading 3 with 3 levels of indentation

Heading 4 with 4 levels of indentation

Heading 5 with 5 levels of indentation
Heading 6 with 6 levels of indentation

Heading 2 with center alignment

Heading 3 with end alignment

This is a paragraph with a text node that contains a new line

Click me! www.atlassian.com

  • First list item

  • Second list item

  • Third list item

  1. First list item

  2. Second list item

  3. Third list item

All that is gold does not glitter, not all those who wander are lost; The old that is strong does not wither, deep roots are not reached by the frost.

From the ashes a fire shall be woken, a light from the shadows shall spring; Renewed shall be blade that was broken, the crownless again shall be king.

J.R.R. Tolkien, The Fellowship of the Ring.


Do not use this image node; it may be removed at any time without notice.

Do not use this image node; it may be removed at any time without notice.

header

header

cell

cell

cell

cell

cell

cell

Media single without width defined

Media single with link

This is the default content of the extension

Extreme node nesting example

 

1

 

2

 

 

Highlights: Light Gray, Light Teal, Light Lime, Light Orange, Light Magenta, Light Purple, Custom: black, Custom: white, Custom: red, Custom: yellow, With inline comment, No highlight

Highlight over comment

Comment over highlight

Partially overlapping comment

</Renderer>

Best practices to prevent performance issues

Avoid unnecessary props changes

As any React component, if props change then it will likely result in a re-render.

Unnecessary props changes will trigger component reconciliation and potential re-renders. This has caused render performance degradation for Editor and Renderer components in the past.

Some common examples of props causing re-renders:

// โŒ function returns new object each time getEventHandlers = () => ({ ...defaultHandlers, newHander: () => { ... } }); // โŒ creates new function each time onRenderComplete = () => { // ... } return ( <ReactRenderer // โŒ passes new object each time media={{ allowLinking: true, }} // โŒ called function returns new object each time eventHandlers={this.getEventHandlers()} // โŒ passes new function each time onComplete={onRenderComplete} // โŒ creates a new function each time onError={() => { ... }} //... />);

Most of these can be generally avoided by following these best practices:

  • extracting static objects to module level constants
  • avoid passing brand new objects and anonymous functions as props upon every render
  • memoising props via helpers like useMemo()
  • use useCallback() for callbacks where applicable

Other best practices for React

Consider using windowing techniques if possible when rendering many Renderers (eg. viewing comments).

For Renderer it is important to avoid redundant reconciliation as it can involve rendering many nested React components, depending on the document structure.

Check out the React docs for more examples of optimizations.

Avoid duplicated dependencies

Ensure you have only have one version of Renderer sub-dependencies (adf-schema, editor-common, prosemirror-model, etc) in your output bundles.

This has caused bugs and crashes on production in the past.

The issue can be avoided by running de-duplication on the lock file or using resolutions for yarn/overrides for npm on the package.json.

Use correct peer dependencies

Make sure to use correct peer dependencies versions!

For example, using newer versions of React or react-dom can cause unexpected issues with Renderer.

Using transformers with the renderer

You will need to use a transformer to convert your own storage format into the ADF before you pass it to the renderer. We have provided helper utility to simplify this process:

import { BitbucketTransformer } from '@atlaskit/editor-bitbucket-transformer'; import { ReactRenderer, ADFEncoder } from '@atlaskit/renderer'; const adfEncoder = new ADFEncoder(schema => new BitbucketTransformer(schema)); const document = adfEncoder.encode(DOCUMENT); ReactDOM.render(<ReactRenderer document={document} />, container);

Polyfills

Don't forget to add polyfills for fetch, ES6 & ES7 to your product build if you want to target older browsers. We recommend the use of babel-preset-env & babel-polyfill

Truncated renderer

The renderer can be truncated with a fade to white so that excess content is hidden. Control of expanding is left to the parent so the text and links can be customised - see the example.

The props truncated, maxHeight and fadeOutHeight are all optional. maxHeight will default to 95px and fadeOutHeight will default to 30px unless defined.

import { ReactRenderer } from '@atlaskit/renderer'; ReactDOM.render(<ReactRenderer document={DOCUMENT} truncated={true} maxHeight={70} fadeOutHeight={30} />, container);

Truncated

Input
<Renderer>

Hello, World! Look I can do italic , strong and underlined text! and action mark and invalid action mark

My favourite emoji are . What are yours?

 

Hi, my name is... My name is... My name is... My name is :D

This is a . And this is a broken

Mention with restricted access

Mentions with generic ids

This is a text with multiple spaces and tabs.

italiclinkstrike-throughstrongsubsupunderline red text

some inline code: const foo = bar();

fallback text in node.attrs.text
fallback text in node.text
[very unknown]

This is text content inside unknown block
This is also a piece of text inside unknown block
Madness?
This is
Sparta!

This is a line with
a hardbreak in it.

Showing a status:

Paragraph with 1 level of indentation

Paragraph with 2 levels of indentation

Paragraph with 3 levels of indentation

Paragraph with 4 levels of indentation

Paragraph with 5 levels of indentation

Paragraph with 6 levels of indentation

Paragraph with center alignment

Paragraph with end alignment

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

Heading 1 with 1 level of indentation

Heading 3 with 3 levels of indentation

Heading 4 with 4 levels of indentation

Heading 5 with 5 levels of indentation
Heading 6 with 6 levels of indentation

Heading 2 with center alignment

Heading 3 with end alignment

This is a paragraph with a text node that contains a new line

Click me! www.atlassian.com

  • First list item

  • Second list item

  • Third list item

  1. First list item

  2. Second list item

  3. Third list item

All that is gold does not glitter, not all those who wander are lost; The old that is strong does not wither, deep roots are not reached by the frost.

From the ashes a fire shall be woken, a light from the shadows shall spring; Renewed shall be blade that was broken, the crownless again shall be king.

J.R.R. Tolkien, The Fellowship of the Ring.


Do not use this image node; it may be removed at any time without notice.

Do not use this image node; it may be removed at any time without notice.

header

header

cell

cell

cell

cell

cell

cell

Media single without width defined

Media single with link

This is the default content of the extension

Extreme node nesting example

 

1

 

2

 

 

Highlights: Light Gray, Light Teal, Light Lime, Light Orange, Light Magenta, Light Purple, Custom: black, Custom: white, Custom: red, Custom: yellow, With inline comment, No highlight

Highlight over comment

Comment over highlight

Partially overlapping comment

 ยท 
</Renderer>

Theming and dark mode support

To render certain ADF content correctly in different color themes, such as light and dark mode, this package utilise the @atlaskit/editor-palette package, which converts colors stored in ADF to Atlassian Design Tokens. Learn more about this utility in the Editor Palette docs.

Full light and dark mode support for the Editor is a work in progress. Currently, the following experiences do not yet support theming:

  • Custom table backgrounds

Props

document import required

@atlaskit/adf-schema.DocNode

dataProviders import

@atlaskit/editor-common/provider-factory.ProviderFactory

eventHandlers import

@atlaskit/editor-common/ui.EventHandlers

extensionHandlers import

@atlaskit/editor-common/extensions.ExtensionHandlers

enableSsrInlineScripts boolean

Enables inline scripts to add support for breakout nodes, before main JavaScript bundle is available.

noOpSSRInlineScript boolean

Enables inline scripts from above on client for first render for hydration to prevent mismatch.

onComplete function

stat => undefined

onError function

Ignored via go/ees005

error => undefined

portal HTMLElement

HTMLElement

rendererContext export

RendererContext

schema import

@atlaskit/editor-prosemirror/model.Schema

appearance union

One of
"comment",
"full-page",
"full-width",
undefined

adfStage import

@atlaskit/editor-common/validator.ADFStage

disableHeadingIDs boolean

disableActions boolean

allowPlaceholderText boolean

maxHeight number

fadeOutHeight number

truncated boolean

createAnalyticsEvent import

@atlaskit/analytics-next.CreateUIAnalyticsEvent

allowColumnSorting boolean

shouldOpenMediaViewer boolean

allowAltTextOnImages boolean

stickyHeaders union

One of
boolean,
show boolean
&
offsetTop number
&
defaultScrollRootId_DO_NOT_USE string
shouldAddDefaultScrollRootOffsetTop_DO_NOT_USE boolean

media object

allowLinking boolean
enableDownloadButton boolean
featureFlags @atlaskit/media-common.MediaFeatureFlags
ssr
mode required @atlaskit/media-common.SSR
config required @atlaskit/media-core.MediaClientConfig
allowCaptions boolean

emojiResourceConfig import

@atlaskit/emoji/resource.EmojiResourceConfig

extensionViewportSizes arrayType

Array
extensionId string
viewportSize string

allowAnnotations boolean

annotationProvider union

One of
@atlaskit/editor-common/types.AnnotationProviders,
null

innerRef React.RefObject<HTMLDivElement>

React.RefObjectHTMLDivElement

useSpecBasedValidator boolean deprecated

{@link https://hello.atlassian.net/browse/ENGHEALTH-3649 Internal documentation for deprecation (no external access)} This prop will be removed and set as default enabled, as the same flag on the Editor is also now default enabled.

allowCopyToClipboard boolean

allowWrapCodeBlock boolean

allowCustomPanels boolean

analyticsEventSeverityTracking object

enabled boolean required
severityNormalThreshold number required
severityDegradedThreshold number required

allowUgcScrubber boolean

allowSelectAllTrap boolean

unsupportedContentLevelsTracking import

@atlaskit/editor-common/utils.UnsupportedContentLevelsTracking

nodeComponents object

[key: string] required React.ComponentTypeReact.PropsWithChildrenany

isInsideOfInlineExtension boolean

isTopLevelRenderer boolean

includeNodesCountInStats boolean

addTelepointer boolean

  • When enabled a trailing telepointer will be added to the rendered document
  • following content updates.
  • Content is updated by passing a new value prop to the renderer.
  • The trailing pointer is updated by dom injection to the last text node which
  • is updated as a result of a content update.

featureFlags union

  • @default undefined
  • @description
  • Short lived feature flags for experiments and gradual rollouts
  • Flags are expected to follow these rules or they are filtered out
    1. cased in kebab-case (match [a-z-])
    1. have boolean values or object {} values
  • @example
  • (<Renderer featureFlags={{ 'my-feature': true }} />);
  • getFeatureFlags()?.myFeature === true;
  • @example
  • (<Renderer featureFlags={{ 'my-feature': 'thing' }} />);
  • getFeatureFlags()?.myFeature === undefined;
  • @example
  • (<Renderer featureFlags={{ 'product.my-feature': false }} />);
  • getFeatureFlags()?.myFeature === undefined;
  • getFeatureFlags()?.productMyFeature === undefined;
One of
[featureFlag: string] boolean required
,
Partial
renderer-render-tracking string required

UNSTABLE_textHighlighter object

pattern required RegExp
component required React.ComponentType
children required React.ReactNode
match string required
marks required Setstring
groups union required One of
Arraystring,
undefined
startPos number required

UNSTABLE_allowTableAlignment boolean

UNSTABLE_allowTableResizing boolean