mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	markup: improve code block readability and isolate copy button (#34009)
Fix #33197 Improve the rendering of code blocks in markdown content for better readability and UI stability across screen sizes. Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		| @@ -86,20 +86,15 @@ func (r *GlodmarkRender) highlightingRenderer(w util.BufWriter, c highlighting.C | ||||
| 			preClasses += " is-loading" | ||||
| 		} | ||||
|  | ||||
| 		err := r.ctx.RenderInternal.FormatWithSafeAttrs(w, `<pre class="%s">`, preClasses) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		// include language-x class as part of commonmark spec, "chroma" class is used to highlight the code | ||||
| 		// the "display" class is used by "js/markup/math.ts" to render the code element as a block | ||||
| 		// the "math.ts" strictly depends on the structure: <pre class="code-block is-loading"><code class="language-math display">...</code></pre> | ||||
| 		err = r.ctx.RenderInternal.FormatWithSafeAttrs(w, `<code class="chroma language-%s display">`, languageStr) | ||||
| 		err := r.ctx.RenderInternal.FormatWithSafeAttrs(w, `<div class="code-block-container code-overflow-scroll"><pre class="%s"><code class="chroma language-%s display">`, preClasses, languageStr) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 	} else { | ||||
| 		_, err := w.WriteString("</code></pre>") | ||||
| 		_, err := w.WriteString("</code></pre></div>") | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										71
									
								
								templates/devtest/markup-render.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								templates/devtest/markup-render.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| {{template "devtest/devtest-header"}} | ||||
| <div class="page-content devtest ui container"> | ||||
| 	{{$longCode := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}} | ||||
| 	<div class="tw-flex"> | ||||
| 		<div class="tw-w-[50%] tw-p-4"> | ||||
| 			<div class="markup render-content"> | ||||
| 				Inline <code>code</code> content | ||||
| 			</div> | ||||
|  | ||||
| 			<div class="divider"></div> | ||||
|  | ||||
| 			<div class="markup render-content"> | ||||
| 				<p>content before</p> | ||||
| 				<pre><code>Very long line with no code block or container: {{$longCode}}</code></pre> | ||||
| 				<p>content after</p> | ||||
| 			</div> | ||||
|  | ||||
| 			<div class="divider"></div> | ||||
|  | ||||
| 			<div class="markup render-content"> | ||||
| 				<p>content before</p> | ||||
| 				<div class="code-block-container code-overflow-wrap"> | ||||
| 					<pre class="code-block"><code>Very long line with wrap: {{$longCode}}</code></pre> | ||||
| 				</div> | ||||
| 				<p>content after</p> | ||||
| 			</div> | ||||
|  | ||||
| 			<div class="divider"></div> | ||||
|  | ||||
| 			<div class="markup render-content"> | ||||
| 				<p>content before</p> | ||||
| 				<div class="code-block-container code-overflow-scroll"> | ||||
| 					<pre class="code-block"><code>Short line in scroll container</code></pre> | ||||
| 				</div> | ||||
| 				<div class="code-block-container code-overflow-scroll"> | ||||
| 					<pre class="code-block"><code>Very long line with scroll: {{$longCode}}</code></pre> | ||||
| 				</div> | ||||
| 				<p>content after</p> | ||||
| 			</div> | ||||
| 		</div> | ||||
|  | ||||
| 		<div class="tw-w-[50%] tw-p-4"> | ||||
| 			<div class="markup render-content"> | ||||
| 				<p>content before</p> | ||||
| 				<div class="code-block-container"> | ||||
| 					<pre class="code-block"><code class="language-math"> | ||||
| 	\lim\limits_{n\rightarrow\infty}{\left(1+\frac{1}{n}\right)^n} | ||||
| 					</code></pre> | ||||
| 				</div> | ||||
| 				<p>content after</p> | ||||
| 			</div> | ||||
|  | ||||
| 			<div class="divider"></div> | ||||
|  | ||||
| 			<div class="markup render-content"> | ||||
| 				<p>content before</p> | ||||
| 				<div class="code-block-container"> | ||||
| 					<pre class="code-block"><code class="language-mermaid is-loading"> | ||||
| 	graph LR | ||||
| 			A[Square Rect] -- Link text --> B((Circle)) | ||||
| 			A --> C(Round Rect) | ||||
| 			B --> D{Rhombus} | ||||
| 			C --> D | ||||
| 					</code></pre> | ||||
| 				</div> | ||||
| 				<p>content after</p> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "devtest/devtest-footer"}} | ||||
| @@ -1,8 +1,3 @@ | ||||
| .markup .code-block, | ||||
| .markup .mermaid-block { | ||||
|   position: relative; | ||||
| } | ||||
|  | ||||
| .markup .code-copy { | ||||
|   position: absolute; | ||||
|   top: 8px; | ||||
| @@ -28,8 +23,8 @@ | ||||
|   background: var(--color-secondary-dark-1) !important; | ||||
| } | ||||
|  | ||||
| .markup .code-block:hover .code-copy, | ||||
| .markup .mermaid-block:hover .code-copy { | ||||
| .markup .code-block-container:hover .code-copy, | ||||
| .markup .code-block:hover .code-copy { | ||||
|   visibility: visible; | ||||
|   animation: fadein 0.2s both; | ||||
| } | ||||
|   | ||||
| @@ -443,13 +443,25 @@ | ||||
| } | ||||
|  | ||||
| .markup pre > code { | ||||
|   padding: 0; | ||||
|   margin: 0; | ||||
|   font-size: 100%; | ||||
| } | ||||
|  | ||||
| .markup .code-block, | ||||
| .markup .code-block-container { | ||||
|   position: relative; | ||||
| } | ||||
|  | ||||
| .markup .code-block-container.code-overflow-wrap pre > code { | ||||
|   white-space: pre-wrap; | ||||
|   overflow-wrap: anywhere; | ||||
|   background: transparent; | ||||
|   border: 0; | ||||
| } | ||||
|  | ||||
| .markup .code-block-container.code-overflow-scroll pre { | ||||
|   overflow-x: auto; | ||||
| } | ||||
|  | ||||
| .markup .code-block-container.code-overflow-scroll pre > code { | ||||
|   white-space: pre; | ||||
|   overflow-wrap: normal; | ||||
| } | ||||
|  | ||||
| .markup .highlight { | ||||
| @@ -470,16 +482,11 @@ | ||||
|   word-break: normal; | ||||
| } | ||||
|  | ||||
| .markup pre { | ||||
|   word-wrap: normal; | ||||
| } | ||||
|  | ||||
| .markup pre code, | ||||
| .markup pre tt { | ||||
|   display: inline; | ||||
|   padding: 0; | ||||
|   line-height: inherit; | ||||
|   word-wrap: normal; | ||||
|   background-color: transparent; | ||||
|   border: 0; | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,8 @@ export function initMarkupCodeCopy(elMarkup: HTMLElement): void { | ||||
|     const btn = makeCodeCopyButton(); | ||||
|     // remove final trailing newline introduced during HTML rendering | ||||
|     btn.setAttribute('data-clipboard-text', el.textContent.replace(/\r?\n$/, '')); | ||||
|     el.after(btn); | ||||
|     // we only want to use `.code-block-container` if it exists, no matter `.code-block` exists or not. | ||||
|     const btnContainer = el.closest('.code-block-container') ?? el.closest('.code-block'); | ||||
|     btnContainer.append(btn); | ||||
|   }); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 D
					D