diff --git a/modules/charset/escape.go b/modules/charset/escape.go
index ce2eb1446..3b1c20697 100644
--- a/modules/charset/escape.go
+++ b/modules/charset/escape.go
@@ -8,6 +8,7 @@
 package charset
 
 import (
+	"bufio"
 	"io"
 	"strings"
 
@@ -31,7 +32,7 @@ func EscapeControlHTML(text string, locale translation.Locale, allowed ...rune)
 	return streamer.escaped, sb.String()
 }
 
-// EscapeControlReaders escapes the unicode control sequences in a provider reader and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte
+// EscapeControlReaders escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte
 func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
 	outputStream := &HTMLStreamerWriter{Writer: writer}
 	streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
@@ -43,6 +44,35 @@ func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.
 	return streamer.escaped, err
 }
 
+// EscapeControlStringReader escapes the unicode control sequences in a provided reader of string content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte
+func EscapeControlStringReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
+	bufRd := bufio.NewReader(reader)
+	outputStream := &HTMLStreamerWriter{Writer: writer}
+	streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
+
+	for {
+		line, rdErr := bufRd.ReadString('\n')
+		if len(line) > 0 {
+			if err := streamer.Text(line); err != nil {
+				streamer.escaped.HasError = true
+				log.Error("Error whilst escaping: %v", err)
+				return streamer.escaped, err
+			}
+		}
+		if rdErr != nil {
+			if rdErr != io.EOF {
+				err = rdErr
+			}
+			break
+		}
+		if err := streamer.SelfClosingTag("br"); err != nil {
+			streamer.escaped.HasError = true
+			return streamer.escaped, err
+		}
+	}
+	return streamer.escaped, err
+}
+
 // EscapeControlString escapes the unicode control sequences in a provided string and returns the findings as an EscapeStatus and the escaped string
 func EscapeControlString(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) {
 	sb := &strings.Builder{}
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index f139a971f..3e3a4efc3 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -9,7 +9,6 @@ import (
 	gocontext "context"
 	"encoding/base64"
 	"fmt"
-	gotemplate "html/template"
 	"io"
 	"net/http"
 	"net/url"
@@ -350,15 +349,13 @@ func renderReadmeFile(ctx *context.Context, readmeFile *namedBlob, readmeTreelin
 		if err != nil {
 			log.Error("Render failed for %s in %-v: %v Falling back to rendering source", readmeFile.name, ctx.Repo.Repository, err)
 			buf := &bytes.Buffer{}
-			ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf, ctx.Locale)
-			ctx.Data["FileContent"] = strings.ReplaceAll(
-				gotemplate.HTMLEscapeString(buf.String()), "\n", `
`,
-			)
+			ctx.Data["EscapeStatus"], _ = charset.EscapeControlStringReader(rd, buf, ctx.Locale)
+			ctx.Data["FileContent"] = buf.String()
 		}
 	} else {
-		ctx.Data["IsRenderedHTML"] = true
+		ctx.Data["IsPlainText"] = true
 		buf := &bytes.Buffer{}
-		ctx.Data["EscapeStatus"], err = charset.EscapeControlReader(rd, &charset.BreakWriter{Writer: buf}, ctx.Locale, charset.RuneNBSP)
+		ctx.Data["EscapeStatus"], err = charset.EscapeControlStringReader(rd, buf, ctx.Locale)
 		if err != nil {
 			log.Error("Read failed: %v", err)
 		}
@@ -492,15 +489,6 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
 			}
 			// to prevent iframe load third-party url
 			ctx.Resp.Header().Add("Content-Security-Policy", "frame-src 'self'")
-		} else if readmeExist && !shouldRenderSource {
-			buf := &bytes.Buffer{}
-			ctx.Data["IsRenderedHTML"] = true
-
-			ctx.Data["EscapeStatus"], _ = charset.EscapeControlReader(rd, buf, ctx.Locale)
-
-			ctx.Data["FileContent"] = strings.ReplaceAll(
-				gotemplate.HTMLEscapeString(buf.String()), "\n", `
`,
-			)
 		} else {
 			buf, _ := io.ReadAll(rd)
 
diff --git a/templates/repo/settings/lfs_file.tmpl b/templates/repo/settings/lfs_file.tmpl
index ce3c39eac..6d20aadde 100644
--- a/templates/repo/settings/lfs_file.tmpl
+++ b/templates/repo/settings/lfs_file.tmpl
@@ -17,11 +17,11 @@
 			
 			
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
+					{{else if .IsPlainText}}
+						{{if .FileContent}}{{.FileContent | Safe}}{{end}}
 					{{else if not .IsTextFile}}
 						{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
+			{{else if .IsPlainText}}
+				{{if .FileContent}}{{.FileContent | Safe}}{{end}}
 			{{else if not .IsTextSource}}