feat: added syntax highlighting to snippets 9b549d95
Steve · 2026-02-18 22:39 6 file(s) · +643 −13
src/darkmatter.tmTheme (added) +560 −0
1 +
<?xml version="1.0" encoding="UTF-8"?>
2 +
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 +
<plist version="1.0">
4 +
<dict>
5 +
	<key>author</key>
6 +
	<string>Template: Chris Kempson, Scheme: metalelf0 (https://github.com/metalelf0)</string>
7 +
	<key>name</key>
8 +
	<string>Base16 Black Metal (Bathory)</string>
9 +
	<key>semanticClass</key>
10 +
	<string>theme.base16.black-metal-bathory</string>
11 +
	<key>colorSpaceName</key>
12 +
	<string>sRGB</string>
13 +
	<key>gutterSettings</key>
14 +
	<dict>
15 +
		<key>background</key>
16 +
		<string>#121212</string>
17 +
		<key>divider</key>
18 +
		<string>#121212</string>
19 +
		<key>foreground</key>
20 +
		<string>#333333</string>
21 +
		<key>selectionBackground</key>
22 +
		<string>#222222</string>
23 +
		<key>selectionForeground</key>
24 +
		<string>#999999</string>
25 +
	</dict>
26 +
	<key>settings</key>
27 +
	<array>
28 +
		<dict>
29 +
			<key>settings</key>
30 +
			<dict>
31 +
				<key>background</key>
32 +
				<string>#121113</string>
33 +
				<key>caret</key>
34 +
				<string>#c1c1c1</string>
35 +
				<key>foreground</key>
36 +
				<string>#c1c1c1</string>
37 +
				<key>invisibles</key>
38 +
				<string>#333333</string>
39 +
				<key>lineHighlight</key>
40 +
				<string>#33333355</string>
41 +
				<key>selection</key>
42 +
				<string>#222222</string>
43 +
			</dict>
44 +
		</dict>
45 +
		<dict>
46 +
			<key>name</key>
47 +
			<string>Text</string>
48 +
			<key>scope</key>
49 +
			<string>variable.parameter.function</string>
50 +
			<key>settings</key>
51 +
			<dict>
52 +
				<key>foreground</key>
53 +
				<string>#c1c1c1</string>
54 +
			</dict>
55 +
		</dict>
56 +
		<dict>
57 +
			<key>name</key>
58 +
			<string>Comments</string>
59 +
			<key>scope</key>
60 +
			<string>comment, punctuation.definition.comment</string>
61 +
			<key>settings</key>
62 +
			<dict>
63 +
				<key>foreground</key>
64 +
				<string>#333333</string>
65 +
			</dict>
66 +
		</dict>
67 +
		<dict>
68 +
			<key>name</key>
69 +
			<string>Punctuation</string>
70 +
			<key>scope</key>
71 +
			<string>punctuation.definition.string, punctuation.definition.variable, punctuation.definition.string, punctuation.definition.parameters, punctuation.definition.string, punctuation.definition.array</string>
72 +
			<key>settings</key>
73 +
			<dict>
74 +
				<key>foreground</key>
75 +
				<string>#c1c1c1</string>
76 +
			</dict>
77 +
		</dict>
78 +
		<dict>
79 +
			<key>name</key>
80 +
			<string>Delimiters</string>
81 +
			<key>scope</key>
82 +
			<string>none</string>
83 +
			<key>settings</key>
84 +
			<dict>
85 +
				<key>foreground</key>
86 +
				<string>#c1c1c1</string>
87 +
			</dict>
88 +
		</dict>
89 +
		<dict>
90 +
			<key>name</key>
91 +
			<string>Operators</string>
92 +
			<key>scope</key>
93 +
			<string>keyword.operator</string>
94 +
			<key>settings</key>
95 +
			<dict>
96 +
				<key>foreground</key>
97 +
				<string>#c1c1c1</string>
98 +
			</dict>
99 +
		</dict>
100 +
		<dict>
101 +
			<key>name</key>
102 +
			<string>Keywords</string>
103 +
			<key>scope</key>
104 +
			<string>keyword</string>
105 +
			<key>settings</key>
106 +
			<dict>
107 +
				<key>foreground</key>
108 +
				<string>#999999</string>
109 +
			</dict>
110 +
		</dict>
111 +
		<dict>
112 +
			<key>name</key>
113 +
			<string>Variables</string>
114 +
			<key>scope</key>
115 +
			<string>variable</string>
116 +
			<key>settings</key>
117 +
			<dict>
118 +
				<key>foreground</key>
119 +
				<string>#5f8787</string>
120 +
			</dict>
121 +
		</dict>
122 +
		<dict>
123 +
			<key>name</key>
124 +
			<string>Functions</string>
125 +
			<key>scope</key>
126 +
			<string>entity.name.function, meta.require, support.function.any-method, variable.function, variable.annotation, support.macro</string>
127 +
			<key>settings</key>
128 +
			<dict>
129 +
				<key>foreground</key>
130 +
				<string>#888888</string>
131 +
			</dict>
132 +
		</dict>
133 +
		<dict>
134 +
			<key>name</key>
135 +
			<string>Labels</string>
136 +
			<key>scope</key>
137 +
			<string>entity.name.label</string>
138 +
			<key>settings</key>
139 +
			<dict>
140 +
				<key>foreground</key>
141 +
				<string>#444444</string>
142 +
			</dict>
143 +
		</dict>
144 +
		<dict>
145 +
			<key>name</key>
146 +
			<string>Classes</string>
147 +
			<key>scope</key>
148 +
			<string>support.class, entity.name.class, entity.name.type.class</string>
149 +
			<key>settings</key>
150 +
			<dict>
151 +
				<key>foreground</key>
152 +
				<string>#e78a53</string>
153 +
			</dict>
154 +
		</dict>
155 +
		<dict>
156 +
			<key>name</key>
157 +
			<string>Classes</string>
158 +
			<key>scope</key>
159 +
			<string>meta.class</string>
160 +
			<key>settings</key>
161 +
			<dict>
162 +
				<key>foreground</key>
163 +
				<string>#c1c1c1</string>
164 +
			</dict>
165 +
		</dict>
166 +
		<dict>
167 +
			<key>name</key>
168 +
			<string>Methods</string>
169 +
			<key>scope</key>
170 +
			<string>keyword.other.special-method</string>
171 +
			<key>settings</key>
172 +
			<dict>
173 +
				<key>foreground</key>
174 +
				<string>#888888</string>
175 +
			</dict>
176 +
		</dict>
177 +
		<dict>
178 +
			<key>name</key>
179 +
			<string>Storage</string>
180 +
			<key>scope</key>
181 +
			<string>storage</string>
182 +
			<key>settings</key>
183 +
			<dict>
184 +
				<key>foreground</key>
185 +
				<string>#999999</string>
186 +
			</dict>
187 +
		</dict>
188 +
		<dict>
189 +
			<key>name</key>
190 +
			<string>Support</string>
191 +
			<key>scope</key>
192 +
			<string>support.function</string>
193 +
			<key>settings</key>
194 +
			<dict>
195 +
				<key>foreground</key>
196 +
				<string>#aaaaaa</string>
197 +
			</dict>
198 +
		</dict>
199 +
		<dict>
200 +
			<key>name</key>
201 +
			<string>Strings, Inherited Class</string>
202 +
			<key>scope</key>
203 +
			<string>string, constant.other.symbol, entity.other.inherited-class</string>
204 +
			<key>settings</key>
205 +
			<dict>
206 +
				<key>foreground</key>
207 +
				<string>#fbcb97</string>
208 +
			</dict>
209 +
		</dict>
210 +
		<dict>
211 +
			<key>name</key>
212 +
			<string>Integers</string>
213 +
			<key>scope</key>
214 +
			<string>constant.numeric</string>
215 +
			<key>settings</key>
216 +
			<dict>
217 +
				<key>foreground</key>
218 +
				<string>#aaaaaa</string>
219 +
			</dict>
220 +
		</dict>
221 +
		<dict>
222 +
			<key>name</key>
223 +
			<string>Floats</string>
224 +
			<key>scope</key>
225 +
			<string>none</string>
226 +
			<key>settings</key>
227 +
			<dict>
228 +
				<key>foreground</key>
229 +
				<string>#aaaaaa</string>
230 +
			</dict>
231 +
		</dict>
232 +
		<dict>
233 +
			<key>name</key>
234 +
			<string>Boolean</string>
235 +
			<key>scope</key>
236 +
			<string>none</string>
237 +
			<key>settings</key>
238 +
			<dict>
239 +
				<key>foreground</key>
240 +
				<string>#aaaaaa</string>
241 +
			</dict>
242 +
		</dict>
243 +
		<dict>
244 +
			<key>name</key>
245 +
			<string>Constants</string>
246 +
			<key>scope</key>
247 +
			<string>constant</string>
248 +
			<key>settings</key>
249 +
			<dict>
250 +
				<key>foreground</key>
251 +
				<string>#aaaaaa</string>
252 +
			</dict>
253 +
		</dict>
254 +
		<dict>
255 +
			<key>name</key>
256 +
			<string>Tags</string>
257 +
			<key>scope</key>
258 +
			<string>entity.name.tag</string>
259 +
			<key>settings</key>
260 +
			<dict>
261 +
				<key>foreground</key>
262 +
				<string>#5f8787</string>
263 +
			</dict>
264 +
		</dict>
265 +
		<dict>
266 +
			<key>name</key>
267 +
			<string>Attributes</string>
268 +
			<key>scope</key>
269 +
			<string>entity.other.attribute-name</string>
270 +
			<key>settings</key>
271 +
			<dict>
272 +
				<key>foreground</key>
273 +
				<string>#aaaaaa</string>
274 +
			</dict>
275 +
		</dict>
276 +
		<dict>
277 +
			<key>name</key>
278 +
			<string>Attribute IDs</string>
279 +
			<key>scope</key>
280 +
			<string>entity.other.attribute-name.id, punctuation.definition.entity</string>
281 +
			<key>settings</key>
282 +
			<dict>
283 +
				<key>foreground</key>
284 +
				<string>#888888</string>
285 +
			</dict>
286 +
		</dict>
287 +
		<dict>
288 +
			<key>name</key>
289 +
			<string>Selector</string>
290 +
			<key>scope</key>
291 +
			<string>meta.selector</string>
292 +
			<key>settings</key>
293 +
			<dict>
294 +
				<key>foreground</key>
295 +
				<string>#999999</string>
296 +
			</dict>
297 +
		</dict>
298 +
		<dict>
299 +
			<key>name</key>
300 +
			<string>Values</string>
301 +
			<key>scope</key>
302 +
			<string>none</string>
303 +
			<key>settings</key>
304 +
			<dict>
305 +
				<key>foreground</key>
306 +
				<string>#aaaaaa</string>
307 +
			</dict>
308 +
		</dict>
309 +
		<dict>
310 +
			<key>name</key>
311 +
			<string>Headings</string>
312 +
			<key>scope</key>
313 +
			<string>markup.heading punctuation.definition.heading, entity.name.section</string>
314 +
			<key>settings</key>
315 +
			<dict>
316 +
				<key>fontStyle</key>
317 +
				<string></string>
318 +
				<key>foreground</key>
319 +
				<string>#888888</string>
320 +
			</dict>
321 +
		</dict>
322 +
		<dict>
323 +
			<key>name</key>
324 +
			<string>Units</string>
325 +
			<key>scope</key>
326 +
			<string>keyword.other.unit</string>
327 +
			<key>settings</key>
328 +
			<dict>
329 +
				<key>foreground</key>
330 +
				<string>#aaaaaa</string>
331 +
			</dict>
332 +
		</dict>
333 +
		<dict>
334 +
			<key>name</key>
335 +
			<string>Bold</string>
336 +
			<key>scope</key>
337 +
			<string>markup.bold, punctuation.definition.bold</string>
338 +
			<key>settings</key>
339 +
			<dict>
340 +
				<key>fontStyle</key>
341 +
				<string>bold</string>
342 +
				<key>foreground</key>
343 +
				<string>#e78a53</string>
344 +
			</dict>
345 +
		</dict>
346 +
		<dict>
347 +
			<key>name</key>
348 +
			<string>Italic</string>
349 +
			<key>scope</key>
350 +
			<string>markup.italic, punctuation.definition.italic</string>
351 +
			<key>settings</key>
352 +
			<dict>
353 +
				<key>fontStyle</key>
354 +
				<string>italic</string>
355 +
				<key>foreground</key>
356 +
				<string>#999999</string>
357 +
			</dict>
358 +
		</dict>
359 +
		<dict>
360 +
			<key>name</key>
361 +
			<string>Code</string>
362 +
			<key>scope</key>
363 +
			<string>markup.raw.inline</string>
364 +
			<key>settings</key>
365 +
			<dict>
366 +
				<key>foreground</key>
367 +
				<string>#fbcb97</string>
368 +
			</dict>
369 +
		</dict>
370 +
		<dict>
371 +
			<key>name</key>
372 +
			<string>Link Text</string>
373 +
			<key>scope</key>
374 +
      <string>string.other.link, punctuation.definition.string.end.markdown, punctuation.definition.string.begin.markdown</string>
375 +
			<key>settings</key>
376 +
			<dict>
377 +
				<key>foreground</key>
378 +
				<string>#5f8787</string>
379 +
			</dict>
380 +
		</dict>
381 +
		<dict>
382 +
			<key>name</key>
383 +
			<string>Link Url</string>
384 +
			<key>scope</key>
385 +
			<string>meta.link</string>
386 +
			<key>settings</key>
387 +
			<dict>
388 +
				<key>foreground</key>
389 +
				<string>#aaaaaa</string>
390 +
			</dict>
391 +
		</dict>
392 +
		<dict>
393 +
			<key>name</key>
394 +
			<string>Lists</string>
395 +
			<key>scope</key>
396 +
			<string>markup.list</string>
397 +
			<key>settings</key>
398 +
			<dict>
399 +
				<key>foreground</key>
400 +
				<string>#5f8787</string>
401 +
			</dict>
402 +
		</dict>
403 +
		<dict>
404 +
			<key>name</key>
405 +
			<string>Quotes</string>
406 +
			<key>scope</key>
407 +
			<string>markup.quote</string>
408 +
			<key>settings</key>
409 +
			<dict>
410 +
				<key>foreground</key>
411 +
				<string>#aaaaaa</string>
412 +
			</dict>
413 +
		</dict>
414 +
		<dict>
415 +
			<key>name</key>
416 +
			<string>Separator</string>
417 +
			<key>scope</key>
418 +
			<string>meta.separator</string>
419 +
			<key>settings</key>
420 +
			<dict>
421 +
				<key>background</key>
422 +
				<string>#222222</string>
423 +
				<key>foreground</key>
424 +
				<string>#c1c1c1</string>
425 +
			</dict>
426 +
		</dict>
427 +
		<dict>
428 +
			<key>name</key>
429 +
			<string>Inserted</string>
430 +
			<key>scope</key>
431 +
			<string>markup.inserted</string>
432 +
			<key>settings</key>
433 +
			<dict>
434 +
				<key>foreground</key>
435 +
				<string>#fbcb97</string>
436 +
			</dict>
437 +
		</dict>
438 +
		<dict>
439 +
			<key>name</key>
440 +
			<string>Deleted</string>
441 +
			<key>scope</key>
442 +
			<string>markup.deleted</string>
443 +
			<key>settings</key>
444 +
			<dict>
445 +
				<key>foreground</key>
446 +
				<string>#5f8787</string>
447 +
			</dict>
448 +
		</dict>
449 +
		<dict>
450 +
			<key>name</key>
451 +
			<string>Changed</string>
452 +
			<key>scope</key>
453 +
			<string>markup.changed</string>
454 +
			<key>settings</key>
455 +
			<dict>
456 +
				<key>foreground</key>
457 +
				<string>#999999</string>
458 +
			</dict>
459 +
		</dict>
460 +
		<dict>
461 +
			<key>name</key>
462 +
			<string>Colors</string>
463 +
			<key>scope</key>
464 +
			<string>constant.other.color</string>
465 +
			<key>settings</key>
466 +
			<dict>
467 +
				<key>foreground</key>
468 +
				<string>#aaaaaa</string>
469 +
			</dict>
470 +
		</dict>
471 +
		<dict>
472 +
			<key>name</key>
473 +
			<string>Regular Expressions</string>
474 +
			<key>scope</key>
475 +
			<string>string.regexp</string>
476 +
			<key>settings</key>
477 +
			<dict>
478 +
				<key>foreground</key>
479 +
				<string>#aaaaaa</string>
480 +
			</dict>
481 +
		</dict>
482 +
		<dict>
483 +
			<key>name</key>
484 +
			<string>Escape Characters</string>
485 +
			<key>scope</key>
486 +
			<string>constant.character.escape</string>
487 +
			<key>settings</key>
488 +
			<dict>
489 +
				<key>foreground</key>
490 +
				<string>#aaaaaa</string>
491 +
			</dict>
492 +
		</dict>
493 +
		<dict>
494 +
			<key>name</key>
495 +
			<string>Embedded</string>
496 +
			<key>scope</key>
497 +
			<string>punctuation.section.embedded, variable.interpolation</string>
498 +
			<key>settings</key>
499 +
			<dict>
500 +
				<key>foreground</key>
501 +
				<string>#999999</string>
502 +
			</dict>
503 +
		</dict>
504 +
		<dict>
505 +
			<key>name</key>
506 +
			<string>Illegal</string>
507 +
			<key>scope</key>
508 +
			<string>invalid.illegal</string>
509 +
			<key>settings</key>
510 +
			<dict>
511 +
				<key>background</key>
512 +
				<string>#5f8787</string>
513 +
				<key>foreground</key>
514 +
				<string>#c1c1c1</string>
515 +
			</dict>
516 +
		</dict>
517 +
		<dict>
518 +
			<key>name</key>
519 +
			<string>Broken</string>
520 +
			<key>scope</key>
521 +
			<string>invalid.broken</string>
522 +
			<key>settings</key>
523 +
			<dict>
524 +
				<key>background</key>
525 +
				<string>#aaaaaa</string>
526 +
				<key>foreground</key>
527 +
				<string>#121113</string>
528 +
			</dict>
529 +
		</dict>
530 +
		<dict>
531 +
			<key>name</key>
532 +
			<string>Deprecated</string>
533 +
			<key>scope</key>
534 +
			<string>invalid.deprecated</string>
535 +
			<key>settings</key>
536 +
			<dict>
537 +
				<key>background</key>
538 +
				<string>#444444</string>
539 +
				<key>foreground</key>
540 +
				<string>#c1c1c1</string>
541 +
			</dict>
542 +
		</dict>
543 +
		<dict>
544 +
			<key>name</key>
545 +
			<string>Unimplemented</string>
546 +
			<key>scope</key>
547 +
			<string>invalid.unimplemented</string>
548 +
			<key>settings</key>
549 +
			<dict>
550 +
				<key>background</key>
551 +
				<string>#333333</string>
552 +
				<key>foreground</key>
553 +
				<string>#c1c1c1</string>
554 +
			</dict>
555 +
		</dict>
556 +
	</array>
557 +
	<key>uuid</key>
558 +
	<string>uuid</string>
559 +
</dict>
560 +
</plist>
src/highlight.rs (added) +37 −0
1 +
use std::io::Cursor;
2 +
use syntect::highlighting::{Theme, ThemeSet};
3 +
use syntect::html::highlighted_html_for_string;
4 +
use syntect::parsing::SyntaxSet;
5 +
6 +
pub struct Highlighter {
7 +
    syntax_set: SyntaxSet,
8 +
    theme: Theme,
9 +
}
10 +
11 +
impl Highlighter {
12 +
    pub fn new() -> Self {
13 +
        let theme_data = include_bytes!("darkmatter.tmTheme");
14 +
        let theme = ThemeSet::load_from_reader(&mut Cursor::new(&theme_data[..]))
15 +
            .expect("failed to load darkmatter theme");
16 +
        Self {
17 +
            syntax_set: SyntaxSet::load_defaults_newlines(),
18 +
            theme,
19 +
        }
20 +
    }
21 +
22 +
    pub fn highlight(&self, name: &str, content: &str) -> String {
23 +
        let ext = name.rsplit('.').next().unwrap_or("");
24 +
        let syntax = self
25 +
            .syntax_set
26 +
            .find_syntax_by_extension(ext)
27 +
            .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
28 +
        highlighted_html_for_string(content, &self.syntax_set, syntax, &self.theme)
29 +
            .unwrap_or_else(|_| {
30 +
                let escaped = content
31 +
                    .replace('&', "&amp;")
32 +
                    .replace('<', "&lt;")
33 +
                    .replace('>', "&gt;");
34 +
                format!("<pre>{}</pre>", escaped)
35 +
            })
36 +
    }
37 +
}
src/lib.rs +1 −0
1 1
pub mod db;
2 +
pub mod highlight;
src/main.rs +26 −10
9 9
};
10 10
use serde::Deserialize;
11 11
use sipp_rust::db::{self, Db};
12 +
use sipp_rust::highlight::Highlighter;
13 +
use std::sync::Arc;
12 14
use tower_http::services::ServeDir;
15 +
16 +
#[derive(Clone)]
17 +
struct AppState {
18 +
    db: Db,
19 +
    highlighter: Arc<Highlighter>,
20 +
}
13 21
14 22
#[derive(Template)]
15 23
#[template(path = "index.html")]
20 28
struct SnippetTemplate {
21 29
    name: String,
22 30
    content: String,
31 +
    highlighted_content: String,
23 32
}
24 33
25 34
#[derive(Template)]
41 50
}
42 51
43 52
async fn view_snippet(
44 -
    State(db): State<Db>,
53 +
    State(state): State<AppState>,
45 54
    Path(short_id): Path<String>,
46 55
) -> Result<WebTemplate<SnippetTemplate>, (StatusCode, Html<String>)> {
47 -
    match db::get_snippet_by_short_id(&db, &short_id) {
48 -
        Some(snippet) => Ok(WebTemplate(SnippetTemplate {
49 -
            name: snippet.name,
50 -
            content: snippet.content,
51 -
        })),
56 +
    match db::get_snippet_by_short_id(&state.db, &short_id) {
57 +
        Some(snippet) => {
58 +
            let highlighted_content = state.highlighter.highlight(&snippet.name, &snippet.content);
59 +
            Ok(WebTemplate(SnippetTemplate {
60 +
                name: snippet.name,
61 +
                content: snippet.content,
62 +
                highlighted_content,
63 +
            }))
64 +
        }
52 65
        None => Err((
53 66
            StatusCode::NOT_FOUND,
54 67
            Html("<h1>Snippet not found</h1>".to_string()),
57 70
}
58 71
59 72
async fn create_snippet(
60 -
    State(db): State<Db>,
73 +
    State(state): State<AppState>,
61 74
    Form(form): Form<CreateSnippetForm>,
62 75
) -> impl IntoResponse {
63 -
    let snippet = db::create_snippet(&db, &form.name, &form.content);
76 +
    let snippet = db::create_snippet(&state.db, &form.name, &form.content);
64 77
    Redirect::to(&format!("/s/{}", snippet.short_id))
65 78
}
66 79
67 80
#[tokio::main]
68 81
async fn main() {
69 -
    let db = db::init_db();
82 +
    let state = AppState {
83 +
        db: db::init_db(),
84 +
        highlighter: Arc::new(Highlighter::new()),
85 +
    };
70 86
71 87
    let app = Router::new()
72 88
        .route("/", get(index))
75 91
        .route("/snippets", post(create_snippet))
76 92
        .nest_service("/assets", ServeDir::new("assets"))
77 93
        .nest_service("/static", ServeDir::new("static"))
78 -
        .with_state(db);
94 +
        .with_state(state);
79 95
80 96
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
81 97
        .await
static/styles.css +15 −0
72 72
	border: 1px solid white;
73 73
}
74 74
75 +
.code-container {
76 +
	border: 1px solid white;
77 +
	height: 400px;
78 +
	overflow: auto;
79 +
}
80 +
81 +
.code-container pre {
82 +
	background-color: #121113 !important;
83 +
	padding: 6px;
84 +
	margin: 0;
85 +
	min-height: 100%;
86 +
	font-size: 13px;
87 +
	line-height: 1.4;
88 +
}
89 +
75 90
button {
76 91
	background: #121113;
77 92
	color: #ffffff;
templates/snippet.html +4 −3
39 39
      <p>by <a target="_blank" href="https://stevedylan.dev">Steve</a></p>
40 40
    </div>
41 41
42 -
    <form id="snippetForm">
42 +
    <div id="snippetForm">
43 43
        <label id="snippetName">{{ name }}</label>
44 -
        <textarea id="content" name="content" rows="10" cols="50" readonly>{{ content }}</textarea>
44 +
        <div class="code-container">{{ highlighted_content|safe }}</div>
45 +
        <textarea id="content" style="display:none;">{{ content }}</textarea>
45 46
      <div class="button-group">
46 47
        <button type="button" id="copyLinkBtn" data-original-text="Copy Link">Copy Link</button>
47 48
        <button type="button" id="copyContentBtn" data-original-text="Copy Content">Copy Content</button>
48 49
        <button type="button" id="createNewBtn">Create New Snippet</button>
49 50
      </div>
50 -
    </form>
51 +
    </div>
51 52
52 53
    <script>
53 54
      async function copyToClipboard(text, button) {