Renderer
Renderer component
yarn add @atlaskit/renderer
113.1.2
Patch Changes
- #118536
b46814682ebf8
- [ux] [ED-26716] Review and fix usage of querySelectors in renderer table - 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
Hello, World! Look I can do italic , strong and underlined text! and action mark and invalid action mark
My favourite emoji are :evilburns: :not-an-emoji:. What are yours?
Apr 2, 2019
Hi, my name is... My name is... My name is... My name is @Oscar Wallhult :D
This is a @mention. And this is a broken @unknown
Mention with restricted access@oscar
Mentions with generic ids@here@all
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 a line with
a hardbreak in it.
Showing a status: In progress
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
// Create a map.
final IntIntOpenHashMap map = new IntIntOpenHashMap();
map.put(1, 2);
map.put(2, 5);
map.put(3, 10);
int count = map.forEach(new IntIntProcedure()
{
int count;
public void apply(int key, int value)
{
if (value >= 5) count++;
}
}).count;
System.out.println("There are " + count + " values >= 5");
First list item
Second list item
Third list item
// Create a map.
final IntIntOpenHashMap map = new IntIntOpenHashMap();
map.put(1, 2);
map.put(2, 5);
map.put(3, 10);
First list item
Second list item
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.
This is an info panel with bold text
This is a note panel with bold text
This is a tip panel with bold text
This is a success panel with bold text
This is a warning panel with bold text
This is a error panel with bold text
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.dfsfdad
asd
- plain text
- all the stuff todo Apr 5, 2019 @Carolyn
- multiline!
asdf
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
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
Hello, World! Look I can do italic , strong and underlined text! and action mark and invalid action mark
My favourite emoji are ๐ :evilburns: :not-an-emoji:. What are yours?
Apr 2, 2019
Hi, my name is... My name is... My name is... My name is @Oscar Wallhult :D
This is a @mention. And this is a broken @unknown
Mention with restricted access@oscar
Mentions with generic ids@here@all
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 a line with
a hardbreak in it.
Showing a status: In progress
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
// Create a map.
final IntIntOpenHashMap map = new IntIntOpenHashMap();
map.put(1, 2);
map.put(2, 5);
map.put(3, 10);
int count = map.forEach(new IntIntProcedure()
{
int count;
public void apply(int key, int value)
{
if (value >= 5) count++;
}
}).count;
System.out.println("There are " + count + " values >= 5");
First list item
Second list item
Third list item
// Create a map.
final IntIntOpenHashMap map = new IntIntOpenHashMap();
map.put(1, 2);
map.put(2, 5);
map.put(3, 10);
First list item
Second list item
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.
This is an info panel with bold text
This is a note panel with bold text
This is a tip panel with bold text
This is a success panel with bold text
This is a warning panel with bold text
This is a error panel with bold text
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.dfsfdad
asd
- plain text
- all the stuff ๐ todo Apr 5, 2019 @Carolyn
- multiline!
asdf
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
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
allowHeadingAnchorLinks
union
One of boolean, activeHeadingId string allowNestedHeaderLinks 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.MediaFeatureFlagsssr mode required @atlaskit/media-common.SSRconfig required @atlaskit/media-core.MediaClientConfigallowCaptions boolean
emojiResourceConfig
import
@atlaskit/emoji/resource.EmojiResourceConfig
smartLinks
object
ssr boolean hideHoverPreview boolean actionOptions undefined.CardProps['actionOptions']frameStyle undefined.CardProps['frameStyle']
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
- cased in kebab-case (match [a-z-])
- 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 , Partialrenderer-render-tracking string required
UNSTABLE_textHighlighter
object
pattern required RegExpcomponent required React.ComponentTypechildren required React.ReactNodematch string required marks required Setstringgroups union required One of Arraystring, undefinedstartPos number required