Skip to content

Commit

Permalink
fix: rich text truncation
Browse files Browse the repository at this point in the history
  • Loading branch information
renrizzolo committed Mar 14, 2023
1 parent 301aa89 commit 40b54d0
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 30 deletions.
57 changes: 27 additions & 30 deletions src/components/RichTextEditor/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import FilePreviewList from './FilePreviewList';
import Popover from '../Popover';
import './styles.css';

const { Modifier, EditorState, convertToRaw, RichUtils, SelectionState } = draftJs;
const { Modifier, EditorState, ContentState, convertToRaw, RichUtils, SelectionState } = draftJs;

const editorStateToHTML = (input) => stateToHTML(input.getCurrentContent());
const editorStateFromHTML = (input, options = {}) =>
Expand Down Expand Up @@ -265,46 +265,43 @@ RichTextEditor.useTruncateState = ({ editorState, briefCharCount, truncateString

const contentState = editorState.getCurrentContent();
const blocks = contentState.getBlocksAsArray();
const lastBlock = contentState.getLastBlock();

let anchor = lastBlock;
let anchorOffset = 0;
let acc = 0;

// get the anchor offset and start block of the text to be removed
for (let i = 0; i < blocks.length; i++) {
const curr = blocks[i];
if (curr.getLength() + acc >= briefCharCount) {
anchor = curr;
const offset = curr.getLength() + acc - briefCharCount;
anchorOffset = offset === 0 ? curr.getLength() : -offset;
let anchorOffset = 0;
let truncatedBlockIndex = 0;

// get the block index and string offset of the text to be truncated
for (const [i, block] of blocks.entries()) {
if (block.getLength() + acc >= briefCharCount) {
truncatedBlockIndex = i;
const offset = block.getLength() + acc - briefCharCount;
anchorOffset = block.getLength() - offset;
break;
}
acc += curr.getLength();
acc += block.getLength();
}

// select from anchor offset to end of last block
const targetRange = new SelectionState({
anchorKey: anchor.getKey(),
anchorOffset,
focusKey: lastBlock.getKey(),
focusOffset: lastBlock.getLength(),
});
let truncatedBlocks = [...blocks].slice(0, truncatedBlockIndex + 1);

const replaced = Modifier.removeRange(contentState, targetRange, 'forward');
// replace the block's text with the truncated text
truncatedBlocks[truncatedBlockIndex] = truncatedBlocks[truncatedBlockIndex].set(
'text',
truncatedBlocks[truncatedBlockIndex].getText().substring(0, anchorOffset)
);

// insert truncateString at end
if (truncateString) {
const end = replaced.getLastBlock();
const newSelection = SelectionState.createEmpty(anchor.getKey())
.set('anchorOffset', end.getLength())
.set('focusOffset', end.getLength());
let newState = ContentState.createFromBlockArray(truncatedBlocks);

const withTruncateString = Modifier.insertText(replaced, newSelection, truncateString, null);
if (truncateString) {
// selection at last character
const endSelection = SelectionState.createEmpty(truncatedBlocks[truncatedBlockIndex].getKey())
.set('anchorOffset', truncatedBlocks[truncatedBlockIndex].getLength())
.set('focusOffset', truncatedBlocks[truncatedBlockIndex].getLength());

return EditorState.push(editorState, withTruncateString, 'remove-range');
// insert truncate string after the last character
newState = Modifier.insertText(newState, endSelection, truncateString);
}
return EditorState.push(editorState, replaced, 'remove-range');

return EditorState.createWithContent(newState);
}, [briefCharCount, editorState, totalCharCount, truncateString]);

return {
Expand Down
6 changes: 6 additions & 0 deletions src/components/RichTextEditor/index.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -468,5 +468,11 @@ describe('<RichTextEditor />', () => {
const { getByTestId } = render(<Component briefCharCount={16} text="<p>abcdefghijklmnop</p><p>q</p>" />);
expect(getByTestId('test').innerHTML).toEqual(`<p>abcdefghijklmnop...</p>`);
});
it('should retain inline styles', () => {
const { getByTestId } = render(
<Component briefCharCount={16} text="<p>abcdefgh<strong>ijkl</strong>mnopq</p>" />
);
expect(getByTestId('test').innerHTML).toEqual(`<p>abcdefgh<strong>ijkl</strong>mnop...</p>`);
});
});
});

0 comments on commit 40b54d0

Please sign in to comment.