3

I am trying to build an site where people write and post it to the database. The text is written in <textarea> and I want to preserve the whitespaces as formatting.

For example, users have to press ENTER to get to a new line from the current one they were typing on, after that, if they want to press ENTER again by writing nothing, that means there will be two new lines, I want to keep the two or more than two new lines restricted to just one blank line.

Stack Overflow has this feature, while writing this line, I pressed enter thrice from the last line, but you can only see one white space.

As I pressed enter 3 times, three <br> were created resulting in three white spaces

How do I achieve this with PHP? I have tried nl2br() but that seems to change every \n to <br \>. How do I solve this issue?

The actual source code:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
</head>

<body>
<form action="" method="post">
<textarea name="ab">
</textarea>
<button>Sub</button></form>
<?php

$post= preg_replace('/\n+/', "\n", $_POST['ab']);
echo nl2br($post);
 
 //echo str_replace($find,$replace,$post);

 
 ?>
</body>
</html>

This is the output html source:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
</head>

<body>
<form action="" method="post">
<textarea name="ab">
</textarea>
<button>Sub</button></form>
This is a single line.<br />
now I pressed enter,<br />
<br />
<br />
three spaces below (should show only 1 whitespace)</body>
</html>

Look at the <br /> created by the nl2br, I want the consecutive <br /r> to be <p>...</p>.

This is what I want to be the output html source:

<!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Untitled Document</title>
    </head>
    
    <body>
    <form action="" method="post">
    <textarea name="ab">
    </textarea>
    <button>Sub</button></form>
    This is a single line.<br />
    now I pressed enter,<br />
    <p>
    three spaces below (should show only 1 whitespace)</p></body>
    </html>
TylerH
  • 20,799
  • 66
  • 75
  • 101
  • you want to prevent it as people are typing in the textarea, or just clean up multi-line blanks after the form's submitted? – Marc B Mar 23 '16 at 21:41
  • I want to clean up the multi-line breaks after submission. –  Mar 23 '16 at 21:42
  • This answer should help: http://stackoverflow.com/questions/4052792/ –  Mar 23 '16 at 22:35
  • @mark.hch It still doesn't work. –  Mar 24 '16 at 06:50
  • This does not work is not a useful information. You should post the exact incoming data from ` $_POST['ab']` and give an example of the desired output for that specific input. Please edit your question to add this information. – maxhb Mar 24 '16 at 07:26
  • @maxhb, look at the html source output in my question. –  Mar 24 '16 at 07:34
  • Did see that but where is the input? Can you provide a [mcve]? – maxhb Mar 24 '16 at 08:48
  • @maxhb That's all the source code I have got. Just run the first one and verify. –  Mar 24 '16 at 08:50
  • `rtrim($textarea);` ? will remove trailing whitespace. – Ryan Vincent Mar 24 '16 at 12:36

4 Answers4

1

Refined my answer based on your new input:

$input = "This is a single line.\nnow I pressed enter,\n\n\nthree spaces below (should show only 1 whitespace)";

$output = preg_replace('/\n\n+([^\n]+)/', "\n" . '<p>$1</p>', $input);
echo nl2br($output);

Output:

This is a single line.<br />
now I pressed enter,<br />
<p>three spaces below (should show only 1 whitespace)</p>
maxhb
  • 8,554
  • 9
  • 29
  • 53
  • look at the html source output in my question. @maxhb –  Mar 24 '16 at 07:41
  • try doing it like this `$input=$_POST['ab']; $output = preg_replace('/\n\n+([^\n]+)/', "\n" . '

    $1

    ', $input); echo nl2br($output);` Since you are taking `\n` directly into the string, it's working, but it doesn't work in the case of `textarea` in this method @maxhb
    –  Mar 24 '16 at 12:12
1

You are possibly on Windows, where a newline is \r\n, not \n like other systems. In fact according to this answer browsers are supposed to normalise newlines from textareas to \r\n always. So maybe that's the problem.

You want to leave single newlines alone, 2 newlines stays as 2 newlines, but 3 or more newlines should collapse to 2 newlines. So try:

$post=preg_replace('/(\r\n){3,}/', "\n\n", $_POST['ab']);
echo nl2br($post);

To collapse 2 or more newlines to properly closed <p>s, as you have in your example output, is a bit harder and I'm not sure you can do it reliably, as it relies that the user create 2 newlines to indicate the start of the <p> and another 2 newlines for the end. If they did not include the 2 ending newlines, you have no end marker for your regex and it will fail to match. Safer to stick with 2 <br>s I think.

As an aside, "whitespace" means any space characters, including spaces, tabs, and newlines; "spaces" means spaces, as between consecutive words; "newlines" means line breaks. Your question mixes up and interchanges these terms, and made it quite hard to understand on the first few reads.

Community
  • 1
  • 1
Don't Panic
  • 13,965
  • 5
  • 32
  • 51
  • Works great! But can you help me specify a css rule to decrease or increase the line-spacing in case of two newlines (which are replaced with `
    `)? @don'tpanic
    – twodee Mar 24 '16 at 13:43
  • @CoderDudeTwodee That's really a separate question but - I don't believe you can style `
    `, and if you modify line-height of the containing element it will affect the lines between text as well. Maybe you could instead change the preg_replace() to replace 3+ newlines with `

    ` instead of `\n\n`, and then control the height of those by having `.spacer {line-height: 1.5;}` (or whatever) in your CSS. Bit clunky but should work.
    – Don't Panic Mar 24 '16 at 14:50
0

How about simply:

$value = preg_replace('/\n\n+/', "\n\n", $value);

That is, replace any sequence of more than two newlines with just one.

VoteyDisciple
  • 37,319
  • 5
  • 97
  • 97
  • Well, it definitely "works" — that code will replace any series of two or more `\n` characters with just two. If it's not doing what you expect, can you post an example of the data before transformation and what exactly needs to be transformed? – VoteyDisciple Mar 23 '16 at 21:45
  • This is the new code- `$post= preg_replace('/\n\n+/', "\n\n", $_POST['ab']); echo nl2br($post);` and this is the output- `john DOE

    john doe



    john doe`
    –  Mar 23 '16 at 21:48
  • From that output it looks like there are spaces in between the newline characters there. (Or are they perhaps `CRLF` pairs?) – VoteyDisciple Mar 23 '16 at 21:50
  • All I did was type 'john doe' on the text area and pressed enter arbitrarily and repeated it thrice. –  Mar 23 '16 at 21:53
  • The spaces you see are actually different lines in the source code. I had to copy it in one line to post it here. –  Mar 23 '16 at 21:54
0

Here's the solution:

$post= preg_replace('/(\n\s*){2,}/', '<br>', $_POST['ab']);
echo nl2br($post);

Now the questions is: Why did I use that regex? It's because textarea leaves one space after every line. To avoid that problem I used an extra \s*. So the PHP will from:

a

b


c

to

a<br>
<br>b<br>
<br>c

Hope that helped :)

PDKnight
  • 712
  • 6
  • 25
  • Yes, it solves that problem, but I want users to be able to output one single blank line with two or more newlines, i.e., if I press enter once, it should work as a `
    ` in the output, but if I press enter twice or more, it should make a new para with `

    `. @PDKnight

    – twodee Mar 24 '16 at 13:07
  • @CoderDudeTwodee Edited. – PDKnight Mar 24 '16 at 13:58