react-draft-wysiwyg
react-draft-wysiwyg copied to clipboard
Remove button should remove all styling
I kind of feel that the "remove" button should remove all styling, links, title styles and bullet points. This is how it works in gmail (remove styling button). Would it be possible to make this consistent with other editors?
Hello @marchaos : in various other editor like this one https://www.froala.com/wysiwyg-editor Remove
option only clears inline formatting.
Nuke-all option (ignores selection). AFAIK just overriding the Remove component would not be enough, so a custom button is needed
import * as React from 'react';
import { EditorState, CharacterMetadata, ContentBlock, ContentState } from 'draft-js';
//NIH https://github.com/facebook/draft-js/issues/166#issuecomment-393488544
const removeInlineStyles = (
editorState: EditorState,
retainInlineStyles: string[] = []
) => {
let blocks = editorState
.getCurrentContent()
.getBlocksAsArray()
.map(singleBlock =>
singleBlock.set(
"characterList",
singleBlock.getCharacterList().map(charMetaData => {
if (!charMetaData) {
return charMetaData;
}
let entity = charMetaData.getEntity();
let style = charMetaData.getStyle();
return CharacterMetadata.create({
entity: entity,
style: style.intersect(retainInlineStyles)
});
})
)
) as ContentBlock[];
return EditorState.createWithContent(
ContentState.createFromBlockArray(blocks)
);
};
interface Props {
editorState?: EditorState,
onChange?: (editorState: EditorState) => void
}
const eraserIcon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNSIgaGVpZ2h0PSIxNSIgdmlld0JveD0iMCAwIDE2IDE2Ij48cGF0aCBkPSJNOC4xIDE0bDYuNC03LjJjLjYtLjcuNi0xLjgtLjEtMi41bC0yLjctMi43Yy0uMy0uNC0uOC0uNi0xLjMtLjZIOC42Yy0uNSAwLTEgLjItMS40LjZMLjUgOS4yYy0uNi43LS42IDEuOS4xIDIuNWwyLjcgMi43Yy4zLjQuOC42IDEuMy42SDE2di0xSDguMXptLTEuMy0uMXMwLS4xIDAgMGwtMi43LTIuN2MtLjQtLjQtLjQtLjkgMC0xLjNMNy41IDZoLTFsLTMgMy4zYy0uNi43LS42IDEuNy4xIDIuNEw1LjkgMTRINC42Yy0uMiAwLS40LS4xLS42LS4yTDEuMiAxMWMtLjMtLjMtLjMtLjggMC0xLjFMNC43IDZoMS44TDEwIDJoMUw3LjUgNmwzLjEgMy43LTMuNSA0Yy0uMS4xLS4yLjEtLjMuMnoiLz48L3N2Zz4=';
export class RichTextCleaner extends React.Component<Props> {
clean = () => {
const { editorState, onChange } = this.props;
onChange(removeInlineStyles(editorState));
}
render() {
return (
<div className="rdw-remove-wrapper" aria-label="rdw-remove-control"onClick={this.clean}>
<div className="rdw-option-wrapper" title="Remove">
<img
src={eraserIcon}
alt=""
/>
</div>
</div>
);
}
}
And then in your editor:
toolbarCustomButtons={[<RichTextCleaner />]}
My First CSS Example
This is a paragraph.
`
h1 { color: white; text-align: center; }
p { font-family: verdana; font-size: 20px; }
My First CSS Example
This is a paragraph.
`
Updated @gytisgreitai solution to only format the selection.
const removeInlineStyles = (editorState: EditorState, retainInlineStyles: string[] = []) => {
const contentState = editorState.getCurrentContent();
const selectionState = editorState.getSelection();
const startKey = selectionState.getStartKey();
const endKey = selectionState.getEndKey();
const startOffset = selectionState.getStartOffset();
const endOffset = selectionState.getEndOffset();
const blocks = contentState.getBlockMap();
let newBlocks = blocks.map((block, blockKey) => {
if (!blockKey) {
return block;
}
let newCharList = block.getCharacterList().map((charMetaData, index) => {
let isWithinSelection = false;
if (blockKey === startKey && blockKey === endKey) {
// Selection starts and ends within this block
isWithinSelection = index >= startOffset && index < endOffset;
} else if (blockKey === startKey) {
// Selection starts in this block
isWithinSelection = index >= startOffset;
} else if (blockKey === endKey) {
// Selection ends in this block
isWithinSelection = index < endOffset;
} else if (blockKey > startKey && blockKey < endKey) {
// Selection spans across this entire block
isWithinSelection = true;
}
if (!isWithinSelection || !charMetaData) {
return charMetaData;
}
let style = charMetaData.getStyle().intersect(retainInlineStyles);
return CharacterMetadata.create({ entity: charMetaData.getEntity(), style: style });
});
return block.set("characterList", newCharList);
});
return EditorState.push(editorState, ContentState.createFromBlockArray(newBlocks.toArray()), 'change-inline-style');
};