How to return raw text and maintain its shape and structure?

Viewed 424

I create a mini-application where users can paste any texts & share it. Let's say the user inputs these texts below.

Ex.

╔══╗
╚╗╔╝
╔╝(¯`v´¯)
╚══`.¸.[Stackoverflow]

When I load it on textarea, it displays correctly.

enter image description here

Link

But when I return raw of that

I kept getting display inline (broken)

╔══╗ ╚╗╔╝ ╔╝(¯`v´¯) ╚══`.¸.[Stackoverflow]

Link


All I did was this

public function raw($uuid)
{
    $paste  = Paste::where('uuid', base64_decode($uuid))->first();

    if($paste->type == 'json'){
        return response()->json($paste->data);
    } else {
        return $paste->raw;
    }
    
}

How can I maintain the same format as I would have render it in my textarea ?


Ex 2.

Display in text-area

▀██▀─▄███▄─▀██─██▀██▀▀█
─██─███─███─██─██─██▄█
─██─▀██▄██▀─▀█▄█▀─██▀█
▄██▄▄█▀▀▀─────▀──▄██▄▄█

Raw Response

As you can see in raw it displays so bad ...

▀██▀─▄███▄─▀██─██▀██▀▀█ ─██─███─███─██─██─██▄█ ─██─▀██▄██▀─▀█▄█▀─██▀█ ▄██▄▄█▀▀▀─────▀──▄██▄▄█

Edit

If I wrap it around pre tag

return '<textarea style="width: 100%; height: 100%;">'. $paste->raw.'</textarea>';

I get a better result

enter image description here

4 Answers

Instead of having to wrap the text in <pre></pre> tags, just apply the CSS property white-space: pre to whichever textarea or other element you are collecting that text in.

Here is the documentation for the pre CSS property: MDN Web Docs: white-space

That will force the line breaks to be respected. That should also copy & paste just fine. Your existing solution already appears to copy and paste just fine for me as well. Make sure to use a monospace font for that text box, as that is necessary to keep all the columns in line.

You can find plenty of great, free monospace font options here on Google Fonts: https://fonts.google.com/?category=Monospace

Examples

Without white-space: pre

** Make sure to click the "Run code snippet" button below to see the rendered preview

<div id="ascii-art" contenteditable>╔══╗
╚╗╔╝
╔╝(¯`v´¯)
╚══`.¸.[Stackoverflow]</div>

✅ With white-space: pre and a monospace font

** Make sure to click the "Run code snippet" button below to see the rendered preview

@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap');

#ascii-art {
  font-family: 'Roboto Mono', monospace;
  white-space: pre;
}
<div id="ascii-art" contenteditable>╔══╗
╚╗╔╝
╔╝(¯`v´¯)
╚══`.¸.[Stackoverflow]</div>

BONUS

If you would like to get all the characters tight and up against each other, add the CSS below:

white-space: pre;
font-family: consolas;
letter-spacing: -0.3px;
line-height: 1.19;

The letter-spacing and line-height values will need to be adjusted slightly as you change the font-family and font-size. Here is that CSS in action for both artworks you provided:

#ascii-art {
  white-space: pre;
  font-family: consolas;
  letter-spacing: -0.3px;
  line-height: 1.19;
}
<div id="ascii-art" contenteditable>▀██▀─▄███▄─▀██─██▀██▀▀█
─██─███─███─██─██─██▄█
─██─▀██▄██▀─▀█▄█▀─██▀█
▄██▄▄█▀▀▀─────▀──▄██▄▄█

╔══╗
╚╗╔╝
╔╝(¯`v´¯)
╚══`.¸.[Stackoverflow]</div>

If you want to use it not inside <pre> which by default preserves new-line chars and also uses monospace font.

  1. Use in style of html tag or in css. font-family: monospace;
  2. Prepare your string by replacing \n with <br/> before injecting into the html tag.

Example: const htmlStr = myStr.replace(/\n/g,'<br/>')

The newline character ('\n'), is not a known html character. It must be replaced with a break tag ('br') for the browser to recognise it. Change your function to globally replace the '\n' with a break tag, which will be rendered by the browser the same way.

public function raw($uuid)
{
    $paste  = Paste::where('uuid', base64_decode($uuid))->first();

    if($paste->type == 'json')
    {
        return response()->json($paste->data);
    }
    else
    {
        return $paste->raw.replace(/\n/g,'<br>');
    }    
}

I believe people misunderstood the question. I believe what OP is asking is how to return the result as a raw text string not part of a website. Something along the lines of old school ASCII art.

If I'm correct in that assumption then the answer is simple. Add:

header("content-type: text/plain");

before your output on the raw page. That will tell the browser to look at the content as a plain text file with end of line characters etc.

Related