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: Pasting String Bypasses CharLimit in textarea #468

Closed
anirudhaCodes opened this issue Jan 28, 2024 · 2 comments · Fixed by #469
Closed

Bug: Pasting String Bypasses CharLimit in textarea #468

anirudhaCodes opened this issue Jan 28, 2024 · 2 comments · Fixed by #469
Labels
bug Something isn't working

Comments

@anirudhaCodes
Copy link
Contributor

Describe the bug
When copying and pasting a string into the textarea, the insertRunesFromUserInput function does not correctly enforce the character limit (CharLimit). As a result, the pasted string exceeds the specified character limit.

Setup

  • OS : WIN 11
  • Shell : bash
  • go Version : go 1.21.6 windows/amd64

To Reproduce
Steps to reproduce the behavior:

  1. Run a form with textarea as a field with charLimit set to some value.
  2. then some chars in the textarea and then copy a big string whose length is more than charLimit.
  3. you will bypass the charlimit.

Current behavior
charlimit is set to 10 for below example.
You can see that pasting String Bypasses CharLimit in textarea
image

Expected behavior
charlimit is set to 10 for below example.
in below case, charLimit is not bypass. (code given in proposed solution is being used for below output ).
image

The textarea should correctly enforce the character limit (CharLimit) when pasting a large string into the textarea.

Proposed solution
textarea/textarea.go file

func (m *Model) insertRunesFromUserInput(runes []rune) {
	// Clean up any special characters in the input provided by the
	// clipboard. This avoids bugs due to e.g. tab characters and
	// whatnot.
	runes = m.san().Sanitize(runes)

	var availSpace int
	if m.CharLimit > 0 {
		availSpace = m.CharLimit - m.Length()
		// If the char limit's been reached, cancel.
		if availSpace <= 0 {
			return
		}
		// If there's not enough space to paste the whole thing cut the pasted
		// runes down so they'll fit.
		if availSpace < len(runes) {
-			runes = runes[:len(runes)-availSpace]
+                     runes = runes[:availSpace]
		}
	}

	// Split the input into lines.
	var lines [][]rune
	lstart := 0
	for i := 0; i < len(runes); i++ {
		if runes[i] == '\n' {
			// Queue a line to become a new row in the text area below.
			// Beware to clamp the max capacity of the slice, to ensure no
			// data from different rows get overwritten when later edits
			// will modify this line.
			lines = append(lines, runes[lstart:i:i])
			lstart = i + 1
		}
	}
	if lstart <= len(runes) {
		// The last line did not end with a newline character.
		// Take it now.
		lines = append(lines, runes[lstart:])
	}

	// Obey the maximum height limit.
	if m.MaxHeight > 0 && len(m.value)+len(lines)-1 > m.MaxHeight {
		allowedHeight := max(0, m.MaxHeight-len(m.value)+1)
		lines = lines[:allowedHeight]
	}

	if len(lines) == 0 {
		// Nothing left to insert.
		return
	}

	// Save the remainder of the original line at the current
	// cursor position.
	tail := make([]rune, len(m.value[m.row][m.col:]))
	copy(tail, m.value[m.row][m.col:])

	// Paste the first line at the current cursor position.
	m.value[m.row] = append(m.value[m.row][:m.col], lines[0]...)
	m.col += len(lines[0])

	if numExtraLines := len(lines) - 1; numExtraLines > 0 {
		// Add the new lines.
		// We try to reuse the slice if there's already space.
		var newGrid [][]rune
		if cap(m.value) >= len(m.value)+numExtraLines {
			// Can reuse the extra space.
			newGrid = m.value[:len(m.value)+numExtraLines]
		} else {
			// No space left; need a new slice.
			newGrid = make([][]rune, len(m.value)+numExtraLines)
			copy(newGrid, m.value[:m.row+1])
		}
		// Add all the rows that were after the cursor in the original
		// grid at the end of the new grid.
		copy(newGrid[m.row+1+numExtraLines:], m.value[m.row+1:])
		m.value = newGrid
		// Insert all the new lines in the middle.
		for _, l := range lines[1:] {
			m.row++
			m.value[m.row] = l
			m.col = len(l)
		}
	}

	// Finally add the tail at the end of the last line inserted.
	m.value[m.row] = append(m.value[m.row], tail...)

	m.SetCursor(m.col)
}
@muesli
Copy link
Member

muesli commented Jan 28, 2024

I have fixed this just the other day. PR incoming.

@muesli muesli added the bug Something isn't working label Jan 28, 2024
@maaslalani
Copy link
Member

Thanks for catching this one @anirudhaCodes & @muesli, PR is merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants