From 0422c3042af9e3cbc1ee48c679cbe774617b0f38 Mon Sep 17 00:00:00 2001 From: eiiko6 Date: Wed, 7 Jan 2026 18:58:53 +0100 Subject: [PATCH] added copy button to code blocks and tweaked some more style --- Cargo.lock | 1 + Cargo.toml | 1 + src/codeblocks.rs | 7 ++++ templates/page.html | 50 +++++++++++++++++++------- templates/style.css | 88 +++++++++++++++++++++++++++++++-------------- 5 files changed, 109 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe64553..259c166 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -208,6 +208,7 @@ dependencies = [ "clap", "lazy_static", "pulldown-cmark", + "pulldown-cmark-escape", "reqwest", "serde", "syntect", diff --git a/Cargo.toml b/Cargo.toml index b3b7529..cad5f3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ chrono = "0.4.42" clap = { version = "4.5.54", features = ["derive"] } lazy_static = "1.5.0" pulldown-cmark = "0.13.0" +pulldown-cmark-escape = "0.11.0" serde = { version = "1.0.228", features = ["derive"] } syntect = "5.3.0" tera = "1.20.1" diff --git a/src/codeblocks.rs b/src/codeblocks.rs index 00abcf7..22f518a 100644 --- a/src/codeblocks.rs +++ b/src/codeblocks.rs @@ -1,4 +1,5 @@ use pulldown_cmark::{CodeBlockKind, CowStr, Event, Parser as MarkdownParser, Tag, TagEnd}; +use pulldown_cmark_escape::escape_html; use syntect::html::highlighted_html_for_string; use crate::{SYNTAX_SET, THEME_SET}; @@ -43,6 +44,12 @@ impl<'a> Iterator for CodeblockRenderer<'a> { let rendered_html = render_code_to_html(&code_content, lang); + let mut escaped_code = String::new(); + let _ = escape_html(&mut escaped_code, &code_content); + + let rendered_html = + rendered_html.replace(" {{ title }} + +
@@ -11,19 +13,43 @@
+ + diff --git a/templates/style.css b/templates/style.css index 70bcfbb..29db02f 100644 --- a/templates/style.css +++ b/templates/style.css @@ -1,16 +1,16 @@ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap'); :root { - --bg-color: #0d0d12; - --container-bg: rgba(25, 25, 35, 0.75); + --bg-color: #0f1116; + --container-bg: #171922; --text-main: #e2e2e9; --text-muted: #a1a1b5; - --accent-pink: #ff4d94; - --accent-pink-glow: rgba(255, 77, 148, 0.3); - --accent-pink-dark: #cc3d76; + --accent: #ff4d94; + --accent-glow: rgba(255, 77, 148, 0.3); + --accent-dark: #cc3d76; - --code-bg: rgba(25, 25, 35, 0.75); + --code-bg: var(--container-bg); --border-color: rgba(255, 255, 255, 0.1); --selection-bg: rgba(255, 77, 148, 0.4); @@ -27,7 +27,6 @@ body { background-color: var(--bg-color); - background-image: radial-gradient(circle at top right, #1a1a2e, #0d0d12); color: var(--text-main); font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; line-height: 1.7; @@ -57,26 +56,29 @@ h1, h2, h3, h4, h5, h6 { h1 { font-size: 2.5rem; - border-bottom: 2px solid var(--accent-pink); padding-bottom: 0.8rem; + margin-bottom: 2.5rem; + border-bottom: 2px solid; + border-image-source: linear-gradient(to right, var(--accent), transparent); + border-image-slice: 1; } h2 { font-size: 1.8rem; - color: var(--accent-pink); + color: var(--accent); } h3 { font-size: 1.5rem; } a { - color: var(--accent-pink); + color: var(--accent); text-decoration: none; transition: color 0.2s ease, text-shadow 0.2s ease; } a:hover { color: #ff80b3; - text-shadow: 0 0 8px var(--accent-pink-glow); + text-shadow: 0 0 8px var(--accent-glow); } p { margin-bottom: 1.2rem; } @@ -91,21 +93,22 @@ li { margin-bottom: 0.5rem; } blockquote { margin: 2rem 0; padding: 0.1rem 1.5rem; - border-left: 4px solid var(--accent-pink); - background: rgba(255, 77, 148, 0.05); + border-left: 4px solid var(--accent); + background: var(--container-bg); border-radius: var(--radius-sm); color: var(--text-muted); font-style: italic; } pre { + position: relative; background: var(--code-bg); background-color: var(--code-bg) !important; padding: 1.2rem; border-radius: var(--radius-md); overflow-x: auto; - border: 1px solid var(--border-color); - margin: 1.5rem 0; + border: 2px solid var(--border-color); + /* margin: 1.5rem 0; */ } code { @@ -117,8 +120,10 @@ code { } pre code { + display: block; background: none !important; padding: 0; + padding-right: 40px; } pre, @@ -140,13 +145,13 @@ table { th { background: rgba(255, 77, 148, 0.1); - color: var(--accent-pink); + color: var(--accent); text-align: left; } th, td { padding: 12px; - border: 1px solid var(--border-color); + border: 2px solid var(--border-color); } tr:nth-child(even) { @@ -155,7 +160,7 @@ tr:nth-child(even) { hr { border: none; - height: 1px; + height: 2px; background: linear-gradient(to right, transparent, var(--border-color), transparent); margin: 3rem 0; } @@ -164,7 +169,7 @@ img { max-width: 100%; border-radius: var(--radius-md); margin: 1.5rem 0; - border: 1px solid var(--border-color); + border: 2px solid var(--border-color); } input[type="checkbox"] { @@ -175,7 +180,7 @@ input[type="checkbox"] { margin-right: 0.5rem; font: inherit; - color: var(--accent-pink); + color: var(--accent); width: 1.25em; height: 1.25em; border: 2px solid var(--text-muted); @@ -193,13 +198,13 @@ input[type="checkbox"]::before { height: 0.65em; transform: scale(0); transition: 120ms transform ease-in-out; - box-shadow: inset 1em 1em var(--accent-pink); + box-shadow: inset 1em 1em var(--accent); clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); } input[type="checkbox"]:checked { - border-color: var(--accent-pink); + border-color: var(--accent); } input[type="checkbox"]:checked::before { @@ -217,8 +222,8 @@ nav { width: 100%; z-index: 1000; background: var(--container-bg); - backdrop-filter: blur(var(--blur-amount)); - -webkit-backdrop-filter: blur(var(--blur-amount)); + /* backdrop-filter: blur(var(--blur-amount)); */ + /* -webkit-backdrop-filter: blur(var(--blur-amount)); */ border-bottom: 1px solid var(--border-color); padding: 1rem 2rem; display: flex; @@ -235,14 +240,14 @@ nav a { } nav a:hover { - color: var(--accent-pink); + color: var(--accent); } .btn { display: inline-block; color: #fff; padding: 0.6rem 1.2rem; - border: solid 1px var(--accent-pink); + border: solid 1px var(--accent); border-radius: var(--radius-md); font-weight: 600; cursor: pointer; @@ -260,3 +265,34 @@ nav a:hover { cursor: not-allowed; border-color: var(--text-muted); } + +.code-wrapper { + position: relative; + margin: 1.5rem 0; +} + +.copy-button { + position: absolute; + top: 10px; + right: 10px; + padding: 10px 10px; + background: var(--container-bg); + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + color: var(--text-muted); + cursor: pointer; + font-size: 0.9rem; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + z-index: 10; +} + +.copy-button:hover { + color: var(--accent); +} + +.copy-button:active { + transform: translateY(2px); +}