Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: While setting content directly while using CharacterCount with limit is not obeyed #5851

Closed
1 task done
gethari opened this issue Nov 21, 2024 · 3 comments · Fixed by #5862 · 4 remaining pull requests
Closed
1 task done

[Bug]: While setting content directly while using CharacterCount with limit is not obeyed #5851

gethari opened this issue Nov 21, 2024 · 3 comments · Fixed by #5862 · 4 remaining pull requests
Labels
Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug

Comments

@gethari
Copy link
Contributor

gethari commented Nov 21, 2024

Affected Packages

core,extension-character-count,react

Version(s)

2.10.x

Bug Description

I thought I messed up something, my editor was not recognizing the content, it was just white screen. After investigating I found out that, I was using CharacterCount extension with limit set to 1000, my content length was longer than that.

  • Can we have a console warning or something to solve the above nightmare for future users ?

Now there's another bug that I found is, my setup use the below way to set the content,

const handleCreate = React.useCallback(
		(editor: Editor) => {
			if (content && editor.isEmpty) {
				editor.commands.setContent(content);
			}
		},
		[content],
	);
	onCreate: ({ editor }) => handleCreate(editor),

While the limit is obeyed and no content is set in the above way, but by directly passing the content to the useEditor hook sets the content in the editor bypassing the limit.

I have added a CodeSandbox to reproduce this issue, please let me know if I can be of help

Browser Used

Firefox

Code Example URL

https://codesandbox.io/p/sandbox/tiptap-react-qidlsv

Expected Behavior

The content should not be set when the limit is set & the size of the content is longer than the allowed limit.

Additional Context (Optional)

No response

Dependency Updates

  • Yes, I've updated all my dependencies.
@gethari gethari added Category: Open Source The issue or pull reuqest is related to the open source packages of Tiptap. Type: Bug The issue or pullrequest is related to a bug labels Nov 21, 2024
@nperez0111
Copy link
Contributor

Character count is implemented as filtering transactions. So if an edit were to occur, it will either reject the transaction or attempt to slice it such that it fits.

filterTransaction: (transaction, state) => {
const limit = this.options.limit
// Nothing has changed or no limit is defined. Ignore it.
if (!transaction.docChanged || limit === 0 || limit === null || limit === undefined) {
return true
}
const oldSize = this.storage.characters({ node: state.doc })
const newSize = this.storage.characters({ node: transaction.doc })
// Everything is in the limit. Good.
if (newSize <= limit) {
return true
}
// The limit has already been exceeded but will be reduced.
if (oldSize > limit && newSize > limit && newSize <= oldSize) {
return true
}
// The limit has already been exceeded and will be increased further.
if (oldSize > limit && newSize > limit && newSize > oldSize) {
return false
}
const isPaste = transaction.getMeta('paste')
// Block all exceeding transactions that were not pasted.
if (!isPaste) {
return false
}
// For pasted content, we try to remove the exceeding content.
const pos = transaction.selection.$head.pos
const over = newSize - limit
const from = pos - over
const to = pos
// It’s probably a bad idea to mutate transactions within `filterTransaction`
// but for now this is working fine.
transaction.deleteRange(from, to)
// In some situations, the limit will continue to be exceeded after trimming.
// This happens e.g. when truncating within a complex node (e.g. table)
// and ProseMirror has to close this node again.
// If this is the case, we prevent the transaction completely.
const updatedSize = this.storage.characters({ node: transaction.doc })
if (updatedSize > limit) {
return false
}
return true
},
}),

This is not run on the initial content (perhaps because the initial content would be expected to be valid?). Because it is waiting for a transaction that changes the document. That can probably be resolved by having a flag that if it has not run before, it can run on a transaction that did not even change the document. A number of transactions go through after creation so only one of them would be needed to trigger the re-evaluation.

Feel free to contribute a PR implementing this or another solution you find.

@gethari
Copy link
Contributor Author

gethari commented Nov 21, 2024

@nperez0111 Thanks for your input, I have raised a PR for this, please take a look when you get a chance

@nperez0111
Copy link
Contributor

v2.10.3 resolves this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment