Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socketโs threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
๐๐ธ A configurable rich text editor based on Draft.js, built for Wagtail
:memo::cocktail: A configurable rich text editor based on Draft.js, built for Wagtail.
Itโs developed alongside our Python Draft.js exporter, for integration into Wagtail. Check out WagtailDraftail, and the editorโs online demo!
This project adheres to Semantic Versioning, and measures performance and code coverage.
Draftail aims for a mouse-free, keyboard-centric experience. Most formatting can be done by using common keyboard shortcuts, inspired by Google Docs and Markdown.
Here are important features worth highlighting:
-
, *
, 1.
to create a list item.##
, code blocks ```
, and more.Draftail is meant to be used in scenarios where not all formatting should be available, and where custom formatting can be necessary. Available formats, built-in and custom, can be specificed declaratively for each editor instance.
Your mileage may vary! There is good support for custom block-level and inline formatting. Custom entities or decorators require knowledge of the Draft.js API, which is very low-level.
First, grab the package from npm:
# Draftail's peerDependencies:
npm install --save draft-js@^0.10.4 react react-dom prop-types
npm install --save draftail
Import the styles for Draft.js, and the editor:
@import 'draft-js/dist/Draft.css';
@import 'draftail/dist/draftail.css';
Then, import the editor and use it in your code. Here is a simple example:
import React from 'react';
import ReactDOM from 'react-dom';
import DraftailEditor, { BLOCK_TYPE, INLINE_STYLE } from '../lib';
const initial = JSON.parse(sessionStorage.getItem('draftail:content'));
const onSave = content => {
console.log('saving', content);
sessionStorage.setItem('draftail:content', JSON.stringify(content));
};
const editor = (
<DraftailEditor
rawContentState={initial || null}
onSave={onSave}
blockTypes={[
{ type: BLOCK_TYPE.HEADER_THREE, label: 'H3' },
{ type: BLOCK_TYPE.UNORDERED_LIST_ITEM, label: 'UL' },
]}
inlineStyles={[
{ type: INLINE_STYLE.BOLD, label: 'B' },
{ type: INLINE_STYLE.ITALIC, label: 'I' },
]}
/>
);
ReactDOM.render(editor, document.querySelector('[data-mount]'));
Finally, be sure to check out the required polyfills.
To change the behavior of the editor, pass props to DraftailEditor
. Here are the available props, and their default values:
// Initial content of the editor. Use this to edit pre-existing content.
rawContentState: null,
// Called when changes occured. Use this to persist editor content.
// Displayed when the editor is empty. Hidden if the user changes styling.
placeholder: null,
onSave: () => {},
// Enable the use of horizontal rules in the editor.
enableHorizontalRule: false,
// Enable the use of line breaks in the editor.
enableLineBreak: false,
// Show undo/redo controls in the toolbar.
showUndoRedoControls: false,
// Disable copy/paste of rich text in the editor.
stripPastedStyles: true,
// Set whether spellcheck is turned on for your editor.
spellCheck: false,
// List of the available block types.
blockTypes: [],
// List of the available inline styles.
inlineStyles: [],
// List of the available entity types.
entityTypes: [],
// List of active decorators.
decorators: [],
// Max level of nesting for unordered and ordered lists. 0 = no nesting.
// Note: Draft.js only provides styles for list nesting up to a depth of 4.
// Please refer to the documentation to add styles for further nesting levels.
maxListNesting: 1,
// Frequency at which the save callback is triggered (ms).
stateSaveInterval: 250,
Draftail, like Draft.js, distinguishes between 3 content formats:
By default, the editor provides the least amount of rich text features. Formats have to be explicitly enabled by the developer, so they have as much control over what rich content is available as possible.
To use a given format, add it to the corresponding list, following the options detailed in the next sections.
// List of the available block types.
blockTypes: [],
// List of the available inline styles.
inlineStyles: [],
// List of the available entity types.
entityTypes: [],
// Unique type shared between block instances.
type: PropTypes.string.isRequired,
// Describes the block in the editor UI, concisely.
label: PropTypes.string,
// Describes the block in the editor UI.
description: PropTypes.string,
// Represents the block in the editor UI.
icon: iconPropType,
// DOM element used to display the block within the editor area.
element: PropTypes.string,
// CSS class(es) added to the block for styling within the editor area.
className: PropTypes.string,
// Unique type shared between inline style instances.
type: PropTypes.string.isRequired,
// Describes the inline style in the editor UI, concisely.
label: PropTypes.string,
// Describes the inline style in the editor UI.
description: PropTypes.string,
// Represents the inline style in the editor UI.
icon: iconPropType,
// CSS properties (in JS format) to apply for styling within the editor area.
style: PropTypes.Object,
// Unique type shared between entity instances.
type: PropTypes.string.isRequired,
// Describes the entity in the editor UI, concisely.
label: PropTypes.string,
// Describes the entity in the editor UI.
description: PropTypes.string,
// Represents the entity in the editor UI.
icon: iconPropType,
// React component providing the UI to manage entities of this type.
source: PropTypes.func.isRequired,
// React component to display inline entities.
decorator: PropTypes.func,
// React component to display block-level entities.
block: PropTypes.func,
// Determines which pieces of content are to be decorated.
strategy: PropTypes.func,
// React component to display the decoration.
component: PropTypes.func,
Draftail is meant to provide a consistent editing experience regardless of what formats (blocks, inline styles, entities) are available. It should be simple for developers to enable/disable a certain format, or to create new ones.
Here are quick questions to help you determine which formatting to use, depending on the use case:
In order to... | Use |
---|---|
Indicate the structure of the content | Blocks |
Enter additional data/metadata | Entities |
Format a portion of a line | Inline styles |
Simple blocks are very easy to create. Add a new block type to blockTypes
, specifying which element
and className
to display the block as.
Here is an example, creating a "Tiny text" block:
blockTypes={[
{
type: 'tiny-text',
label: 'Tiny',
element: 'div',
className: 'u-tinytext',
},
]}
More advanced blocks, requiring custom React components, aren't supported at the moment. If you need this, feel free to create an issue.
Custom inline styles only require a style
prop, defining which CSS properties to apply when the format is active.
Here is a basic example:
inlineStyles={[
{
label: 'Redacted',
type: 'REDACTED',
style: {
backgroundColor: 'currentcolor',
},
},
]}
It is also possible to override the styling of predefined inline styles:
inlineStyles={[
{
label: 'Bold',
type: INLINE_STYLE.BOLD,
style: {
fontWeight: 'bold',
textShadow: '1px 1px 1px black',
},
},
]}
Creating custom entity types is a bit more involved because entities aren't simply on/off: they often need additional data (thus a UI to enter this data), and can be edited.
Apart from the usual label/type/icon options, entities need:
source
, a React component that will be used to create/edit the entity from a specific data source (could be an API, or a form inside of a modal).decorator
, a React component to display the entity within the editor area.For now, please refer to the examples available with the project.
Decorators receive the current textual content as children
, as well as the entity key and content state. They can then render the entity based on its data:
const Link = ({ entityKey, contentState, children }) => {
const { url } = contentState.getEntity(entityKey).getData();
return (
<span title={url} className="Link">
{children}
</span>
);
};
Custom decorators follow the Draft.js CompositeDecorator API.
Without custom controls, the editor has a very simple UI and its styles are relatively straightforward. To make sure everything works, use a CSS reset, like Normalize.css.
To tweak the editor UI, Draftail uses old-fashioned stable, namespaced class names that you are free to add more styles to. For example, the toolbar uses .Draftail-Toolbar
.
Draftail also makes its Sass stylesheets available for extension:
// Increase the default editor z-index.
$editor-z-index: 100;
// Import all of the styles in your build.
@import 'draftail/lib/index';
// Alternatively, only import the constants to reuse them elsewhere in your project.
@import 'draftail/lib/api/constants';
Draft.js only provides default styles for list nesting up to five levels (depth 0 to 4). If you want to allow more nesting, you will need to add the list styles.
Draftail provides a helper Sass mixin which adds OL counters and indentation, and can be used like:
@import 'draftail/lib/api/nested-list-item';
// Add nesting support up to 7 levels.
@for $depth from 5 through 6 {
@include nested-list-item($depth);
}
Supported browser / device versions:
Browser | Device/OS | Version |
---|---|---|
Mobile Safari | iOS Phone | latest |
Mobile Safari | iOS Tablet | latest |
Chrome | Android | latest |
IE | Desktop | 11 |
Chrome | Desktop | latest |
MS Edge | Windows | latest |
Firefox | Desktop | latest |
Safari | OSX | latest |
Draft.js and Draftail build upon ES6 language features. If targeting browsers that do not support them, have a look at:
position: sticky
support, and stickyfill
polyfill.Element.closest()
support, and polyfill.The Draftail demo site lists minimum polyfills for IE11 support: examples/utils/polyfills.js
.
See anything you like in here? Anything missing? We welcome all support, whether on bug reports, feature requests, code, design, reviews, tests, documentation, and more. Please have a look at our contribution guidelines.
If you just want to set up the project on your own computer, the contribution guidelines also contain all of the setup commands.
Draftail is made possible by the work of Springload, a New Zealand digital agency, and core contributors to the Wagtail CMS. The beautiful demo site is the work of @thibaudcolas.
View the full list of contributors. MIT licensed. Website content available as CC0.
DraftUtils.getEntitySelection(editorState, entityKey)
method, returning the selection corresponding to a given entity. Note: only works if the entity is in the currently selected block.DraftUtils.updateBlockEntity
method, with workaround for Draft.s 0.10 entity data update bug.public-DraftStyleDefault-depth${depth}
.nested-list-item($depth)
Sass mixin to generate styles for arbitrary list item nesting.Draftail-
class namespace for all styles (#63).Icon
implementation to use SVG by default. Supports symbol references, SVG path(s), and arbitrary React components (#119).Tooltip
outside of Draftail package.data-tooltip
.Portal
component outside of Draftail.block
prop to entityTypes, and move IMAGE
and EMBED
blocks outside of Draftail (#121).entityTypes
' block
to edit, remove entity.DraftUtils.getSelectedEntitySelection
. It can be replaced by DraftUtils.getEntitySelection(editorState, DraftUtils.getSelectionEntity(editorState))
.MODEL
entities.EMBED
entities.DOCUMENT
entities.entityTypes
' imageFormats
.entityTypes
strategy
.FAQs
๐๐ธ A configurable rich text editor built with Draft.js
The npm package draftail receives a total of 1,431 weekly downloads. As such, draftail popularity was classified as popular.
We found that draftail demonstrated a not healthy version release cadence and project activity because the last version was released a year ago.ย It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socketโs threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.