Skip to content

Fix #19368 - Improve line ending handling in grid editor#20076

Open
og-khushalpatel wants to merge 16 commits intophpmyadmin:QA_5_2from
og-khushalpatel:fix/preserve-crlf-on-value-click
Open

Fix #19368 - Improve line ending handling in grid editor#20076
og-khushalpatel wants to merge 16 commits intophpmyadmin:QA_5_2from
og-khushalpatel:fix/preserve-crlf-on-value-click

Conversation

@og-khushalpatel
Copy link

Description

This pull request adds explicit line ending (CRLF / LF) handling to inline grid editing for text-like fields.
Browsers normalize textarea input to LF, which previously made it impossible for users to reliably view, preserve, or intentionally change the original line-ending format stored in the database. This PR addresses that gap by:

  • Detecting the original line-ending format (CRLF or LF) on the server
  • Exposing a line-ending selector in the inline edit area for applicable text fields
  • Allowing users to preserve or intentionally change the line-ending format
  • Ensuring idempotent behavior to avoid duplicated line breaks on repeated edits
  • Keeping rendering and comparison logic consistent across truncated and non-truncated values
    The implementation follows existing phpMyAdmin patterns and avoids altering behavior for non-textual field types.

Fixes #19368 - \r\n is replaced with \n when clicking on a value

Before submitting pull request, please review the following checklist:

  • [ X ] Make sure you have read our CONTRIBUTING.md document.
  • [ X ] Make sure you are making a pull request against the correct branch. For example, for bug fixes in a released version use the corresponding QA branch and for new features use the master branch. If you have a doubt, you can ask as a comment in the bug report or on the mailing list.
  • [ X ] Every commit has proper Signed-off-by line as described in our DCO. This ensures that the work you're submitting is your own creation.
  • [ X ] Every commit has a descriptive commit message.
  • [ X ] Every commit is needed on its own, if you have just minor fixes to previous commits, you can squash them.
  • Any new functionality is covered by tests.

Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
@liviuconcioiu
Copy link
Contributor

liviuconcioiu commented Feb 5, 2026

It fixes the issue, except it introduces an old bug #17398. It also happens on empty values, without NULL.

05.02.2026_16.30.32_REC.mp4

Also, I think it should be Line ending:, without s, since only one line ending can be selected and work at a time. Also, the help icon should be moved after :.

Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
@og-khushalpatel
Copy link
Author

Hi @liviuconcioiu ,
thanks a lot for the review and for pointing these things out.

Just to clarify one point: the change in this PR does not introduce the old bug #17398 which has been demonstrated in the attached video. That said, I agree with your observation that it also occurs on empty values without NULL. I’ve addressed that case now in the latest update.

I’ve also updated the label to Line ending: (singular) and moved the help icon after the colon, as suggested.

Please let me know if you’d like me to adjust anything further. Thanks again for the helpful feedback!
[Screencast from 2026-02-06 19-50-46.webm]
(https://github.com/user-attachments/assets/9e5aadd7-66b5-4eb7-8ebb-e6b338e7abee)

@liviuconcioiu
Copy link
Contributor

UPDATE is still being triggered:

06.02.2026_16.50.48_REC.mp4

@og-khushalpatel
Copy link
Author

@liviuconcioiu I’ve gone through the scenario again on my end and also shared the recording as proof, but I’m still unable to reproduce the issue you’re observing. To make sure I’m not missing something, could you please share the exact table structure/schema (including column types and any relevant constraints) that you’re using when encountering this problem?
Having the precise structure would really help me set up the same environment locally and understand where the mismatch might be coming from. I’d like to ensure the fix works correctly for your case as well.
Thanks in advance for your help.

@liviuconcioiu
Copy link
Contributor

I use MariaDB 12.2.1 on Windows.

CREATE TABLE `test` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `colA` varchar(255) DEFAULT NULL,
  `colB` varchar(255) NOT NULL,
  `colC` int(10) unsigned DEFAULT NULL,
  `colD` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`colD`)),
  `colE` uuid DEFAULT NULL,
  `colF` timestamp(6) NOT NULL DEFAULT current_timestamp(6),
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

INSERT INTO `test` (`id`, `colA`, `colB`, `colC`, `colD`, `colE`, `colF`) VALUES
(1, 'Lynne', 'Combs', 1, '{\"test\":100}', '7b42b69b-f744-11f0-9d12-806d971fcc98', '2026-01-22 03:43:14.629614'),
(2, 'Carlos', 'Lara', NULL, NULL, NULL, '2026-01-22 03:43:46.727948'),
(3, NULL, 'Lang', 200, '{\"x\":\"y\"}', NULL, '2026-01-22 03:44:20.661601'),
(4, NULL, '', NULL, NULL, 'c0b2cf7a-f744-11f0-9d12-806d971fcc98', '2026-01-22 03:45:11.126818');

Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
@og-khushalpatel
Copy link
Author

og-khushalpatel commented Feb 8, 2026

Hi @liviuconcioiu, thanks for sharing the exact table structure/schema.
This turned out to be caused by jQuery’s .data() cache auto-casting values (numbers / JSON objects) on first access, which broke the comparison. Normalizing both sides fixes it.. I’ve now normalized both the canonical old and new values before comparison, which avoids the unnecessary updates you mentioned.
Please let me know if this looks correct from your side.

@liviuconcioiu
Copy link
Contributor

Found another problem. If I change the line ending to a cell from LF to CRLF, the cell below will have the same line ending as the first, instead of keeping it.

CREATE TABLE `test` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `value` text DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

INSERT INTO `test` (`id`, `value`) VALUES
(1, 'test\ntest'),
(2, 'test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test <td class=\"text-right\">\n        test test test test test test test test test test test test test test test test test test test test</td>');
08.02.2026_10.56.03_REC.mp4

Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
@og-khushalpatel
Copy link
Author

Found another problem. If I change the line ending to a cell from LF to CRLF, the cell below will have the same line ending as the first, instead of keeping it.

Hi @liviuconcioiu, just a quick update! The issue you mentioned is now fixed. It was due to stale event handlers in the grid editor. Would appreciate a quick review when you’re free.

@liviuconcioiu
Copy link
Contributor

Everything is okay now!

if (isNull) {
$thisField.find('span').html('NULL');
$thisField.addClass('null');
// todo: set original value to null & remove data-line-ending attribute
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this todo be done ? or removed ?

Comment on lines 700 to 701
? data.truncatableFieldValue.replace(/\r\n/g, '\n')
: $thisField.data('value').replace(/\r\n/g, '\n');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please call normalizeNewlines

'<span class="line-ending-label">' +
'Line ending:' +
'<span>' +
'<img src="themes/dot.gif" title="The suggested value was detected from your existing data." alt="The suggested value was detected from your existing data." class="icon ic_b_help">' +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not hard code messages, they need to be translated
Please check other examples in the codebase

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @williamdes,

I have added new translatable strings in JavaScriptMessagesController.php (e.g. __('Line ending:')). After running update-po, the entries were added to .po files but marked as #, fuzzy.

Since I’m new to contributing, I wanted to clarify the expected workflow:

Should I manually resolve/remove the fuzzy entries and include the updated .po files in this PR?
Or should I avoid committing any translation file changes and let the maintainers/translators handle that separately?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not. Those are added weekly by cron job. You don't need to add .po files to PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification.
I’m still learning the project conventions, so I appreciate the guidance. I’ll make sure not to include .po files.

canonicalOldValue = String(Functions.normalizeNewlines(Functions.getCellValue(g.currentEditCell)));
}
// Normalizing to LFs only for text comparison.
canonicalNewValue = (String(canonicalNewValue)).replace(/\r\n/g, '\n');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call normalizeNewlines

Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Signed-off-by: Khushal Patel <khushal.b.patel01@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants