ftml/render/html/element/
text.rs

1/*
2 * render/html/element/text.rs
3 *
4 * ftml - Library to parse Wikidot text
5 * Copyright (C) 2019-2025 Wikijump Team
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21use super::prelude::*;
22
23pub fn render_wikitext_raw(ctx: &mut HtmlContext, text: &str) {
24    debug!("Escaping raw string '{text}'");
25
26    ctx.html()
27        .span()
28        .attr(attr!(
29            "class" => "wj-raw",
30        ))
31        .contents(text);
32}
33
34pub fn render_email(ctx: &mut HtmlContext, email: &str) {
35    debug!("Rendering email address '{email}'");
36
37    // Since our usecase doesn't typically have emails as real,
38    // but rather as fictional elements, we're just rendering as text.
39
40    ctx.html()
41        .span()
42        .attr(attr!("class" => "wj-email"))
43        .contents(email);
44}
45
46pub fn render_code(ctx: &mut HtmlContext, language: Option<&str>, contents: &str) {
47    debug!(
48        "Rendering code block (language {})",
49        language.unwrap_or("<none>"),
50    );
51    let index = ctx.next_code_snippet_index();
52    ctx.handle().post_code(index, contents);
53
54    let class = {
55        let mut class = format!("wj-code wj-language-{}", language.unwrap_or("none"));
56        class.make_ascii_lowercase();
57        class
58    };
59
60    ctx.html()
61        .element("wj-code")
62        .attr(attr!("class" => &class))
63        .inner(|ctx| {
64            // Panel for holding additional features
65            ctx.html()
66                .div()
67                .attr(attr!(
68                    "class" => "wj-code-panel",
69                ))
70                .inner(|ctx| {
71                    let button_title = ctx
72                        .handle()
73                        .get_message(ctx.language(), "button-copy-clipboard");
74
75                    // Copy to clipboard button
76                    ctx.html()
77                        .element("wj-code-copy")
78                        .attr(attr!(
79                            "type" => "button",
80                            "class" => "wj-code-copy",
81                            "title" => button_title,
82                        ))
83                        .inner(|ctx| {
84                            ctx.html().sprite("wj-clipboard");
85                            // Hidden normally, shown when clicked
86                            ctx.html().sprite("wj-clipboard-success");
87                        });
88
89                    // Span showing name of language
90                    ctx.html()
91                        .span()
92                        .attr(attr!(
93                            "class" => "wj-code-language",
94                        ))
95                        .contents(language.unwrap_or(""));
96                });
97
98            // Code block containing highlighted contents
99            ctx.html().pre().inner(|ctx| {
100                ctx.html().code().contents(contents);
101            });
102        });
103}