Skip to content

Commit efd1b8e

Browse files
committed
Polish code block rendering
1 parent 1be0904 commit efd1b8e

5 files changed

Lines changed: 198 additions & 22 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "webifier-extensions"
7-
version = "1.0.6"
7+
version = "1.0.7"
88
description = "First-party extensions for Webifier static sites."
99
readme = "README.md"
1010
license = "MIT"

webifier_extensions/standard/assets/css/main.css

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,87 @@ footer {
170170
font-size: 0.95rem;
171171
}
172172

173+
.codehilite,
174+
.wf-code-block {
175+
position: relative;
176+
margin: 1rem 0;
177+
overflow: hidden;
178+
background: var(--wf-code-bg, var(--bs-tertiary-bg, #f8f9fa));
179+
border: 1px solid var(--wf-code-border, var(--bs-border-color, #dee2e6));
180+
border-radius: 0.45rem;
181+
}
182+
183+
.codehilite pre,
184+
.wf-code-block pre {
185+
margin: 0;
186+
padding: 1rem 1.1rem;
187+
overflow: auto;
188+
color: var(--wf-code-text, var(--bs-body-color, #212529));
189+
background: transparent;
190+
font-size: 0.86rem;
191+
line-height: 1.55;
192+
tab-size: 4;
193+
}
194+
195+
.codehilite pre,
196+
.wf-code-block.has-copy pre {
197+
padding-right: 4.25rem;
198+
}
199+
200+
.app-content :not(pre) > code {
201+
padding: 0.08rem 0.28rem;
202+
color: var(--wf-code-inline-text, var(--bs-body-color, #212529));
203+
background: var(--wf-code-inline-bg, var(--bs-tertiary-bg, #f8f9fa));
204+
border-radius: 0.25rem;
205+
font-size: 0.88em;
206+
}
207+
208+
.wf-code-copy {
209+
position: absolute;
210+
top: 0.45rem;
211+
right: 0.45rem;
212+
z-index: 2;
213+
display: inline-flex;
214+
align-items: center;
215+
justify-content: center;
216+
min-width: 3.1rem;
217+
height: 1.65rem;
218+
padding: 0 0.45rem;
219+
color: var(--wf-code-copy-color, var(--bs-secondary-color, #6c757d));
220+
background: var(--wf-code-copy-bg, rgba(255, 255, 255, 0.78));
221+
border: 1px solid var(--wf-code-copy-border, var(--bs-border-color, #dee2e6));
222+
border-radius: 999px;
223+
font-size: 0.72rem;
224+
line-height: 1;
225+
opacity: 0;
226+
transform: translateY(-0.15rem);
227+
transition:
228+
opacity 0.14s ease,
229+
transform 0.14s ease,
230+
color 0.14s ease,
231+
border-color 0.14s ease;
232+
}
233+
234+
.codehilite:hover .wf-code-copy,
235+
.codehilite:focus-within .wf-code-copy,
236+
.wf-code-block:hover .wf-code-copy,
237+
.wf-code-block:focus-within .wf-code-copy {
238+
opacity: 1;
239+
transform: translateY(0);
240+
}
241+
242+
.wf-code-copy:hover,
243+
.wf-code-copy:focus {
244+
color: var(--wf-code-copy-hover-color, var(--bs-body-color, #212529));
245+
border-color: var(--wf-code-copy-hover-border, var(--bs-secondary-color, #6c757d));
246+
}
247+
248+
.wf-code-copy.is-copied {
249+
color: var(--wf-code-copy-success-color, #198754);
250+
border-color: var(--wf-code-copy-success-border, #198754);
251+
opacity: 1;
252+
}
253+
173254
.wf-page-chrome h1 {
174255
margin-bottom: 0;
175256
}
@@ -228,4 +309,9 @@ footer {
228309
.wf-page-navigation .small {
229310
font-size: 0.78rem;
230311
}
312+
313+
.wf-code-copy {
314+
opacity: 0.82;
315+
transform: none;
316+
}
231317
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
(function () {
2+
document.addEventListener("DOMContentLoaded", function () {
3+
var candidates = Array.prototype.slice.call(document.querySelectorAll(".codehilite, pre"));
4+
candidates.forEach(function (candidate) {
5+
var block = candidate;
6+
var pre = candidate.matches("pre") ? candidate : candidate.querySelector("pre");
7+
if (!pre || pre.dataset.wfCodeReady === "true") {
8+
return;
9+
}
10+
if (candidate.matches("pre")) {
11+
var highlightedParent = candidate.closest(".codehilite");
12+
if (highlightedParent) {
13+
return;
14+
}
15+
block = document.createElement("div");
16+
block.className = "wf-code-block";
17+
candidate.parentNode.insertBefore(block, candidate);
18+
block.appendChild(candidate);
19+
}
20+
block.classList.add("has-copy");
21+
pre.dataset.wfCodeReady = "true";
22+
23+
var button = document.createElement("button");
24+
button.type = "button";
25+
button.className = "wf-code-copy";
26+
button.textContent = "Copy";
27+
button.setAttribute("aria-label", "Copy code to clipboard");
28+
block.appendChild(button);
29+
30+
button.addEventListener("click", function () {
31+
var code = pre.innerText;
32+
var copied = navigator.clipboard && window.isSecureContext
33+
? navigator.clipboard.writeText(code)
34+
: new Promise(function (resolve, reject) {
35+
var textarea = document.createElement("textarea");
36+
textarea.value = code;
37+
textarea.setAttribute("readonly", "");
38+
textarea.style.position = "fixed";
39+
textarea.style.top = "-1000px";
40+
document.body.appendChild(textarea);
41+
textarea.select();
42+
try {
43+
document.execCommand("copy") ? resolve() : reject();
44+
} catch (error) {
45+
reject(error);
46+
}
47+
document.body.removeChild(textarea);
48+
});
49+
copied.then(function () {
50+
button.textContent = "Copied";
51+
button.classList.add("is-copied");
52+
window.setTimeout(function () {
53+
button.textContent = "Copy";
54+
button.classList.remove("is-copied");
55+
}, 1200);
56+
}).catch(function () {
57+
button.textContent = "Failed";
58+
window.setTimeout(function () {
59+
button.textContent = "Copy";
60+
}, 1200);
61+
});
62+
});
63+
});
64+
});
65+
})();

webifier_extensions/standard/templates/macros/head.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
</script>
4242
<link rel="stylesheet" href="{{ baseurl }}/assets/css/codehilite.css">
4343
<link rel="stylesheet" href="{{ baseurl }}/assets/css/main.css">
44+
<script defer src="{{ baseurl }}/assets/js/codeblocks.js"></script>
4445
{% if builder %}
4546
{{ builder.render_extension_area("head", baseurl=baseurl, config=config, page=data, ctx=ctx) }}
4647
{% endif %}

webifier_extensions/theme/assets/css/theme.css

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@
88
--wf-shadow: rgba(0, 0, 0, 0.15);
99
--wf-header-overlay: rgba(255, 255, 255, 0.75);
1010
--wf-image-overlay: rgba(0, 0, 0, 0.5);
11+
--wf-code-bg: #f8f9fa;
12+
--wf-code-border: #d8dee4;
13+
--wf-code-text: #24292f;
14+
--wf-code-inline-bg: rgba(175, 184, 193, 0.2);
15+
--wf-code-inline-text: #24292f;
16+
--wf-code-copy-bg: rgba(255, 255, 255, 0.86);
17+
--wf-code-copy-color: #57606a;
18+
--wf-code-copy-border: #d0d7de;
19+
--wf-code-copy-hover-color: #24292f;
20+
--wf-code-copy-hover-border: #8c959f;
21+
--wf-code-copy-success-color: #1a7f37;
22+
--wf-code-copy-success-border: #1a7f37;
1123
}
1224

1325
:root[data-bs-theme="dark"] {
@@ -20,6 +32,18 @@
2032
--wf-shadow: rgba(0, 0, 0, 0.45);
2133
--wf-header-overlay: rgba(17, 20, 24, 0.78);
2234
--wf-image-overlay: rgba(0, 0, 0, 0.62);
35+
--wf-code-bg: #1e1e1e;
36+
--wf-code-border: #3c3c3c;
37+
--wf-code-text: #d4d4d4;
38+
--wf-code-inline-bg: #2d2d2d;
39+
--wf-code-inline-text: #d4d4d4;
40+
--wf-code-copy-bg: rgba(30, 30, 30, 0.88);
41+
--wf-code-copy-color: #cccccc;
42+
--wf-code-copy-border: #555555;
43+
--wf-code-copy-hover-color: #ffffff;
44+
--wf-code-copy-hover-border: #858585;
45+
--wf-code-copy-success-color: #89d185;
46+
--wf-code-copy-success-border: #89d185;
2347
}
2448

2549
body,
@@ -153,30 +177,30 @@ pre {
153177
}
154178

155179
:root[data-bs-theme="dark"] .codehilite {
156-
background: #0d1117;
157-
color: #e6edf3;
180+
background: var(--wf-code-bg);
181+
color: var(--wf-code-text);
158182
}
159183

160184
:root[data-bs-theme="dark"] .codehilite pre {
161-
background: #0d1117;
162-
color: #e6edf3;
163-
border: 1px solid #30363d;
185+
background: transparent;
186+
color: var(--wf-code-text);
187+
border: 0;
164188
}
165189

166-
:root[data-bs-theme="dark"] .codehilite .hll { background-color: #2d333b; }
190+
:root[data-bs-theme="dark"] .codehilite .hll { background-color: #264f78; }
167191
:root[data-bs-theme="dark"] .codehilite .c,
168192
:root[data-bs-theme="dark"] .codehilite .ch,
169193
:root[data-bs-theme="dark"] .codehilite .cm,
170194
:root[data-bs-theme="dark"] .codehilite .cpf,
171195
:root[data-bs-theme="dark"] .codehilite .c1,
172-
:root[data-bs-theme="dark"] .codehilite .cs { color: #8b949e; }
196+
:root[data-bs-theme="dark"] .codehilite .cs { color: #6a9955; }
173197
:root[data-bs-theme="dark"] .codehilite .k,
174198
:root[data-bs-theme="dark"] .codehilite .kc,
175199
:root[data-bs-theme="dark"] .codehilite .kd,
176200
:root[data-bs-theme="dark"] .codehilite .kn,
177201
:root[data-bs-theme="dark"] .codehilite .kp,
178-
:root[data-bs-theme="dark"] .codehilite .kr,
179-
:root[data-bs-theme="dark"] .codehilite .nt { color: #ff7b72; }
202+
:root[data-bs-theme="dark"] .codehilite .kr { color: #c586c0; }
203+
:root[data-bs-theme="dark"] .codehilite .nt { color: #9cdcfe; }
180204
:root[data-bs-theme="dark"] .codehilite .s,
181205
:root[data-bs-theme="dark"] .codehilite .s1,
182206
:root[data-bs-theme="dark"] .codehilite .s2,
@@ -190,31 +214,31 @@ pre {
190214
:root[data-bs-theme="dark"] .codehilite .ss,
191215
:root[data-bs-theme="dark"] .codehilite .dl,
192216
:root[data-bs-theme="dark"] .codehilite .l,
193-
:root[data-bs-theme="dark"] .codehilite .ld { color: #a5d6ff; }
217+
:root[data-bs-theme="dark"] .codehilite .ld { color: #ce9178; }
194218
:root[data-bs-theme="dark"] .codehilite .m,
195219
:root[data-bs-theme="dark"] .codehilite .mb,
196220
:root[data-bs-theme="dark"] .codehilite .mf,
197221
:root[data-bs-theme="dark"] .codehilite .mh,
198222
:root[data-bs-theme="dark"] .codehilite .mi,
199223
:root[data-bs-theme="dark"] .codehilite .mo,
200-
:root[data-bs-theme="dark"] .codehilite .il { color: #79c0ff; }
224+
:root[data-bs-theme="dark"] .codehilite .il { color: #b5cea8; }
201225
:root[data-bs-theme="dark"] .codehilite .na,
202-
:root[data-bs-theme="dark"] .codehilite .nb,
203-
:root[data-bs-theme="dark"] .codehilite .nc,
204-
:root[data-bs-theme="dark"] .codehilite .nf,
205-
:root[data-bs-theme="dark"] .codehilite .nn,
206226
:root[data-bs-theme="dark"] .codehilite .nv,
207-
:root[data-bs-theme="dark"] .codehilite .bp,
208-
:root[data-bs-theme="dark"] .codehilite .fm,
209227
:root[data-bs-theme="dark"] .codehilite .vc,
210228
:root[data-bs-theme="dark"] .codehilite .vg,
211229
:root[data-bs-theme="dark"] .codehilite .vi,
212-
:root[data-bs-theme="dark"] .codehilite .vm { color: #d2a8ff; }
230+
:root[data-bs-theme="dark"] .codehilite .vm { color: #9cdcfe; }
231+
:root[data-bs-theme="dark"] .codehilite .nb,
232+
:root[data-bs-theme="dark"] .codehilite .bp { color: #dcdcaa; }
233+
:root[data-bs-theme="dark"] .codehilite .nc,
234+
:root[data-bs-theme="dark"] .codehilite .nn { color: #4ec9b0; }
235+
:root[data-bs-theme="dark"] .codehilite .nf,
236+
:root[data-bs-theme="dark"] .codehilite .fm { color: #dcdcaa; }
213237
:root[data-bs-theme="dark"] .codehilite .o,
214238
:root[data-bs-theme="dark"] .codehilite .ow,
215239
:root[data-bs-theme="dark"] .codehilite .p,
216-
:root[data-bs-theme="dark"] .codehilite .w { color: #e6edf3; }
240+
:root[data-bs-theme="dark"] .codehilite .w { color: var(--wf-code-text); }
217241
:root[data-bs-theme="dark"] .codehilite .err {
218-
color: #ffdcd7;
219-
border-color: #f85149;
242+
color: #f44747;
243+
border-color: #f44747;
220244
}

0 commit comments

Comments
 (0)