Problem/Motivation
In #2844452: Export configuration YAML strings as multiline, we earned neat readable exports for multiline config items IFF they do not contain "\r".
Many config contain \r though, simply for lazynesss, as the HTML standard mandates textarea elements to return "\r\n" line breaks.
Proposed resolution
Add a "#normalize_newlines" option to \Drupal\Core\Render\Element\Textarea.
So beautifying config is a oneliner for module developers.
Remaining tasks
Do it.
User interface changes
None.
API changes
Add a "#normalize_newlines" option to \Drupal\Core\Render\Element\Textarea.
Data model changes
None.
Release notes snippet
The Textarea element has a now "#normalize_newlines" option.
Config before... config after...
Example form element...
| Comment | File | Size | Author |
|---|
Issue fork drupal-3202631
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
geek-merlinOK, feature and tests are in MR, and green.
Comment #4
longwaveCould we just turn this on by default? Is there a reason we might want to keep \r\n instead of \n?
Comment #5
geek-merlin> Could we just turn this on by default? Is there a reason we might want to keep \r\n instead of \n?
Just the usual BC considerations. Not sure about this, but i wanted to avoid that discusssion. But let's have it.
Comment #6
geek-merlin@andypost Thanks for the pronto review, all resolved.
Open: Suggestion in #4 to have this on by default.
Comment #7
longwaveI can't think of a reason when the line endings actually matter. They don't otherwise matter in PHP and
nl2br()accepts any line ending style. The HTML5 spec suggests that web browsers use only \n internally to represent line breaks and then normalize to send \r\n as the value. There is however the chance of some custom code that interprets the line breaks in some way and expects them to be \r\n.I think the BC way of doing this would be to add this flag, warn users that this will change in Drupal 10 if the flag is not set, and then remove the flag (or change the default to TRUE) in Drupal 10.
But then, is this the right thing to do for all textareas, or is this really only important for ones that deal with config entities? Instead could typed data be responsible for normalisation for storage?
Comment #8
geek-merlin> Instead could typed data be responsible for normalisation for storage?
Good point. Some time passed since i groked the internals, but if this is on storage (not on export), i'd favor that over this approach.
Comment #9
geek-merlin@longwave:
> Instead could typed data be responsible for normalisation for storage?
Use the source, Luke: TypedData does NOT mess with primitive data, it only validates via constraints.
StorableConfigBase OTOH already massages data on save() (not on setValue()) in \Drupal\Core\Config\StorableConfigBase::castValue (so the stored config has other sort as in-memory config, which may also violate the principle of least surprise for some).
- So we can add a constraint to string TypedData.
- And we can normalize newlines in StorableConfigBase::castValue (but let's get a signal from code owners if they are open to that).
I'll add a bold proposal for that.
Done: #3202796: Default to normalize newlines in "text" config to \n
Comment #11
damienmckennaComment #12
damienmckennaThis is the MR as of commit b02df751 in patch format, not going to run tests as it'd be redundant.
Comment #13
damienmckennaThis changes the patch so that the default on the new option is TRUE instead of FALSE.
Comment #14
damienmckennaThe interdiff in #13 was made incorrectly, this is the correct one.
Comment #15
damienmckennaFYI #13 works with core textarea fields, as used on the Account Settings page, but does not work with Webform's settings pages.
Comment #16
damienmckennaI added an issue to discuss supporting this in Webform: #3239878: Support multiline config export via #3202631
Comment #17
damienmckennaFYI I opened an issue for the core bug that can cause the blank last line of config files to be removed: https://www.drupal.org/project/drupal/issues/3240104
Comment #18
longwaveAssume the MR is the one to review here (we need the default FALSE for backward compatibility), but the tests are failing.
Comment #19
damienmckennaHow's about this?
Comment #20
geek-merlinCodewise: I wonder if and why we need
!emptyto get green, but if that solves it, so be it.We still have to settle the question if we want the default behavior changed for better DX, and if the deprecation fuss is worth it.
Comment #22
damienmckennaA minor change to make sure the string has a lineline character at the end.
Comment #24
eric_a commented$value = preg_replace('~\r\n?~u', "\n", $value);Why this and not the same code as in
Drupal\filter\Element\ProcessedText::preRenderText()? Better to be consistent I guess.The #normalize_newlines option is an interesting one and a very usable one in my mind. Drupal has so many textfields that are used to input a list of one-liners. In those cases it's very helpful to normalize the set of items. The form with the textfield has the knowledge wether this normalisation is a good idea. The configuration layer cannot know if the CRLF newline has any special meaning.
I wonder if core has some places where this type of normalization is already being executed on textarea. It would be good then to implement this in those case.
Comment #25
joseph.olstadThis is needed for DX (Developer eXperience), particularly, I have a very large webform, while it does import and export with PostgreSQL no problem, it crashes on MySQL locales_table column too small unless the \r\n is normalized to \n which core handles now see 2844452
as a fix for the locales table crashing in MySQL, a continuation of #2844452: Export configuration YAML strings as multiline
this is because my setup is using more than one language and the config yaml translations are being stored in the locales_source table which on mysql will crash on 64kb+ long strings unless the line endings are normalized.
The issue is, the GUI tools inside the webform module are generating \r\n , some are, some aren't. this is for things like css entry and js entry for webforms and webform confirmation message configuration.
So it keeps reverting to \r\n even though I'm wanting \n.
so, for now, if I want to import this onto a Drupal install using a MySQL type db I need to run my super huge webform yml through dos2unix THEN process it (every !/$**/ time).
This is tedious and can be very frustrating for those that haven't figured out the bug because they could be stumped completely by it.
With that said, postgresql handles this like a breaze because I believe it just stores a blob for these configs when storing to the locales_source table.
Comment #27
joseph.olstadComment #28
joseph.olstadBased on patch #18, modified as per comments in #24, using same strategy already implemented in
core/modules/filter/src/Element/ProcessedText.phpwhich is consistent with what is already being used by core.
Comment #29
joseph.olstadPatch works well.
I applied the core patch, then added
to the
css_editor/css_editor.modulecontrib module form markupthen I rebuilt cache, edited the theme css (as per css_editor added functionality)
saved the css
then exported css
before fix the exported yml looked like '****'
Now the output yml generated by drush cex is legible and looks like:
I suspect the patch will pass testing.
Comment #30
joseph.olstadComment #31
geek-merlinCode looks straightforward to me.
Contains a test, yay!
Needs CR.
When re-uploading the patch, you should
- first add the test-only patch (expected: red)
- then the full patch (expected: green)
So to prove that the test tests what it advertises.
Nit: Unrelated change.
Comment #33
klonosThis comment line here exceeds the 80char limit.
Comment #34
sahil.goyal commentedHi I addressed the comment #33 and clear all the warning which shown earlier patch, so i uploaded the patch along with the interadiff.
Comment #35
sahil.goyal commentedComment #36
ameymudras commented@sahil did a code review and there are a few observations.
- Unrelated changes mentioned in #34 have not yet been addressed in the patch above
- The comment can probably be better worded
- We should break the comment closer to 80 chars
Comment #38
abrammThe patch in #34 doesn't apply to 10.3, so re-rolled it against both 10.3.x (for those of us who need this patch to be applied to their sites) and 11.x branches.
Also, removed the unrelated change and split patches to test and test+fix.
Comment #43
abrammAdded two MRs (test only and test + code change), let's see if tests still passes.
Comment #45
andypostThanks, looks good to me
Comment #46
andypostComment #47
catchThis seems good but still needs a change record.
Comment #50
taran2lSmall code update + added a change record. Please review
Comment #51
solideogloria commentedIt looks like the test is failing.
Comment #52
andypostOne test still fails
Comment #53
solideogloria commentedThe test was working earlier, back when it was this:
Comment #54
taran2lIt's green now.
I've refactored test a bit to be more robust and support more cases.
Comment #55
smustgrave commentedRan test-only feature to see coverage
Summary appears complete
Code change itself seems pretty straight forward
LGTM!
Comment #57
quietone commentedThere are no unanswered questions here and is does look straight forward as said in the previous comment.
Unfortunately, one of the comments was not wrapped correctly. I updated that one and made a change to another.
I then reviewed the test and found that most of the defaults for the element did not need to be set. That lead me to rework the test and the data provider. The data provider now sets the element configuration as needed and the structure is changed as well.
This now needs another review.
Comment #58
quietone commentedComing back to check the change record. I see no evidence here that anyone has reviewed the change record. I took a brief look and was overwhelmed by the second paragraph with a long sentence that is hard to parse. Remember, the readers of change records will have varying levels of skills with the English language.
Setting to needs work for a review of the change record.
Comment #59
solideogloria commentedThe comment changes look good to me.
Comment #61
tim.plunkettBig rebase after #3525331: Reuse element plugins as object wrappers around render arrays.
I rewrote the CR.
Changing from a task to a bug, as evidenced by #3536318: \r\n on the config form causes the property_restrictions to not be followed
Comment #62
tim.plunkettComment #63
dcam commentedI'm pretty sure there is duplication between this issue and #3226410: CRLF causes mismatch between JS and form maxlength validation.
Comment #64
godotislate1 small comment on the MR.
Also, @alexpott brought up in #3226410: CRLF causes mismatch between JS and form maxlength validation #27 that normalizing "\r\n" to "\n" will cause values to be stored differently between form and JSON:API submissions when textareas are used in entity form widgets. Should core widgets set their textarea's
#normalize_newlinesproperty toFALSE?Comment #65
smustgrave commentedSmall comments on the MR with 1 question.
Comment #66
godotislatePushed a commit addressing #64 with a test and also the MR comment about type declarations.
I think #3226410: CRLF causes mismatch between JS and form maxlength validation can be closed as a duplicate now and credit ported here.
Ready for review again.
Comment #67
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #68
joseph.olstadJustification:
Comment #69
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #70
godotislateRebased and applied outstanding suggestion.
Comment #71
smustgrave commentedRebase seems good.
Comment #74
quietone commented@tim.plunkett, thanks for rewriting the change record. I have reviewed it and it is very clear what this change is.
I read the MR and changed 2 comments which didn't read correctly. Leaving at RTBC
Comment #75
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #76
godotislateThe MR rebased clean with no conflicts, so back to RTBC.
Comment #77
grayle commentedI saw this comment in the merge request:
But all browsers on all OSes themselves normalize textarea text newlines to `\r\n` when they bundle it up to send as form data. So if you send it to JSON:API with `\n` and then edit that entity and save the form via the admin UI, that value will receive `\r\n` instead on Mac, Windows, Linux, doesn't matter. `\r\n` is the HTML standard.
https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#...
They recently changed the spec (2021) to change how interacting with textareas works via JS.
https://github.com/whatwg/html/pull/6697
https://github.com/whatwg/html/issues/6647
But that does not matter when the form is eventually submitted via multipart/form-data, that still normalizes everything to CRLF.
Comment #78
godotislateRe #77, the discussion about standard browser normalization behavior to CRLF and JSON:API started in #3226410-27: CRLF causes mismatch between JS and form maxlength validation. The concern is that JSON:API submissions with data containing "\r\n" will not be normalized to "\n", resulting in data being stored differently depending on submission method.
I think some of that discussion might be under the assumption that
application/jsonsubmissions are normalized to CRLF the same asmultipart/form-data,application/x-www-form-urlencoded, ortext/plain. It seems like that might not be the case? In which case, the line endings for text content submitted via JSON:API might vary based on the OS where the content was authored?Comment #79
grayle commentedI am going off of old school Core REST with the standard json format, not JSON:API, but when someone sends a string with only LF in it as
application/json, that is what gets stored in the database. If I then edit that entity in the UI, and save it, those LFs get normalized to CRLF due to the HTML spec browsers enforce.Currently, when the values are submitted via a form I am comparing the new value to the old value and if they match exactly after line ending normalization, I keep the old value to respect whatever line endings already exist in the database. Otherwise I normalize to LF, which breaks fewer things than CRLF afaik.
I would normalize on the consumer side, but it is a generic field and should respect whatever line endings the user sent the text in because it gets used as a source to replace certain tokens in files. Could be LF, CR, CRLF, whatever was sent should be kept. That is an edge case, of course.
But, yes, seems like the OS matters. And what sends it matters. I think
application/jsonhas no spec or enforcement, and even if it did not all clients capable of sendingapplication/jsonwould follow it. Postman, curl, a JS framework that does or does not normalize line endings, wrap=hard being turned on in a textarea, the list goes on.It should be easy enough to test: POST some data with just LF to a textarea via JSON:API or Core REST JSON, print it somewhere as a json encoded string to see the lack of carriage returns and presence of line feeds, then save it via the admin interface and you should see that carriage returns have snuck in. And this should happen on any OS, in any browser.
Comment #80
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #81
smustgrave commentedFixed the test since summary is no longer shipped.
Comment #82
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #83
godotislateRebased.
Comment #84
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #85
godotislateRebased and set issue version to main.
Comment #86
codebymikey commentedAttached a static copy of the current patch for 11.x
Comment #87
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #88
godotislateBack to RTBC.
Comment #89
alexpottThere's a merge conflict that needs to be addressed. Also I feel as though this issue should introduce the capability and not change the default behaviour then we should discuss the default in a followup. For me this has a non-zero chance of breaking something somewhere. So we should be a bit cautious. There hasn't been a discussion on the issue to say why we've not followed @longwave's suggestion in #7.
Comment #91
prudloff commentedI fixed the merge conflicts but the concerns from #89 still need to be addressed.