The Battle for Wesnoth  1.19.10+dev
markup.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2024 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "color.hpp"
18 #include "exceptions.hpp"
19 // This file isn't needed by any of these functions, but this allows any
20 // standard color to be passed to span_color without an extra include.
21 #include "font/standard_colors.hpp"
22 #include "formatter.hpp"
23 
24 #include <string>
25 #include <string_view>
26 #include <vector>
27 
28 class config;
29 
30 namespace markup
31 {
32 /**
33  * Wraps the given data in the specified tag.
34  *
35  * @param tag The tag ("b", "i", etc).
36  * @param data The content to wrap with @a tag.
37  * Each argument must be writable to a stringstream.
38  *
39  * @note Special formatting characters in the input are not escaped.
40  * If such behavior is needed, it must be handled by the caller.
41  * If the concatenation of @a data results in an empty string,
42  * an empty string is returned in lieu of formatting tags.
43  */
44 template<typename... Args>
45 std::string tag(std::string_view tag, Args&&... data)
46 {
47  std::string input = (formatter() << ... << data);
48  if(input.empty()) return {};
49  return formatter() << "<" << tag << ">" << input << "</" << tag << ">";
50 }
51 
52 /** @todo is it safe to use a string_view for both key and value */
53 using tag_attributes = std::vector<std::pair<std::string_view, std::string_view>>;
54 
55 /**
56  * Wraps the given data in the specified tag.
57  *
58  * @param tag The tag ("b", "i", etc).
59  * @param attrs A vector containing the attribute key-value pairs.
60  * @param data The content to wrap with @a tag.
61  * Each argument must be writable to a stringstream.
62  *
63  * @note Special formatting characters in the input are not escaped.
64  * If such behavior is needed, it must be handled by the caller.
65  * If the concatenation of @a data results in an empty string,
66  * an empty string is returned in lieu of formatting tags.
67  */
68 template<typename... Args>
69 std::string tag(std::string_view tag, const tag_attributes& attrs, Args&&... data)
70 {
71  std::string input = (formatter() << ... << data);
72  if(input.empty()) return {};
73  std::stringstream ss;
74  ss << "<" << tag << " ";
75  for (const auto& [key, value] : attrs) {
76  ss << key << "='" << value << "' ";
77  }
78  ss << ">" << input << "</" << tag << ">";
79  return ss.str();
80 }
81 
82 /**
83  * Wraps the given data in a @c span tag with the specified attribute and value.
84  *
85  * @param key The span attribute ("color", "size", etc).
86  * @param value The attribute value.
87  * @param data The content to format.
88  *
89  * @note See @ref tag for more information.
90  */
91 template<typename Value, typename... Args>
92 std::string span_attribute(std::string_view key, const Value& value, Args&&... data)
93 {
94  return tag("span", {{ key, value }}, std::forward<Args>(data)...);
95 }
96 
97 /**
98  * Applies Pango markup to the input specifying its display color.
99  *
100  * @param color The color_t object from which to retrieve the color.
101  * @param data Variable list of content to enclose inside the span tag.
102  * Each argument must be writable to a stringstream.
103  *
104  * @returns @code `<span color='#color'>#data</span>` @endcode
105  *
106  * @note Special formatting characters in the input are not escaped.
107  * If such behavior is needed, it must be handled by the caller.
108  */
109 template<typename... Args>
110 std::string span_color(const color_t& color, Args&&... data)
111 {
112  return span_attribute("color", color.to_hex_string(), std::forward<Args>(data)...);
113 }
114 
115 /**
116  * Applies Pango markup to the input specifying its display color.
117  *
118  * @param color The hex color string.
119  * @param data Variable list of content to enclose inside the span tag.
120  * Each argument must be writable to a stringstream.
121  *
122  * @returns @code `<span color='#color'>#data</span>` @endcode
123  *
124  * @note Special formatting characters in the input are not escaped.
125  * If such behavior is needed, it must be handled by the caller.
126  */
127 template<typename... Args>
128 std::string span_color(std::string_view color, Args&&... data)
129 {
130  return span_attribute("color", color, std::forward<Args>(data)...);
131 }
132 
133 /**
134  * Applies Pango markup to the input specifying its display size.
135  *
136  * @param size A Pango string size specifier (large, small, x-large, etc).
137  * @param data Variable list of content to concatenate inside the span tag.
138  * Each argument must be writable to a stringstream.
139  *
140  * @returns @code `<span size='#size'>#data</span>` @endcode
141  *
142  * @note Special formatting characters in the input are not escaped.
143  * If such behavior is needed, it must be handled by the caller.
144  */
145 template<typename... Args>
146 std::string span_size(std::string_view size, Args&&... data)
147 {
148  return span_attribute("size", size, std::forward<Args>(data)...);
149 }
150 
151 /**
152  * Applies bold Pango markup to the input.
153  *
154  * @param data Variable list of content to concatenate inside the bold tag.
155  * Each argument must be writable to a stringstream.
156  *
157  * @note Special formatting characters in the input are not escaped.
158  * If such behavior is needed, it must be handled by the caller.
159  */
160 template<typename... Args>
161 std::string bold(Args&&... data)
162 {
163  return tag("b", std::forward<Args>(data)...);
164 }
165 
166 /**
167  * Applies italic Pango markup to the input.
168  *
169  * @param data Variable list of content to enclose inside the italic tag.
170  * Each argument must be writable to a stringstream.
171  *
172  * @note Special formatting characters in the input are not escaped.
173  * If such behavior is needed, it must be handled by the caller.
174  */
175 template<typename... Args>
176 std::string italic(Args&&... data)
177 {
178  return tag("i", std::forward<Args>(data)...);
179 }
180 
181 /**
182  * Generates a Help markup tag corresponding to an image.
183  *
184  * @param src The WML path to the image (i.e., 'units/drakes/arbiter.png')
185  * @param align Alignment of the image. Possible values: left, right, center.
186  * @param floating Is the image a floating image or an inline image?
187  *
188  * @note Special formatting characters in the input are not escaped.
189  * If such behavior is needed, it must be handled by the caller.
190  * @see gui2::rich_label for details on how this tag is parsed.
191  */
192 std::string img(const std::string& src, const std::string& align = "left", bool floating = false);
193 
194 /**
195  * Generates a Help markup tag corresponding to a reference or link.
196  *
197  * @param text User visible text/caption of the link.
198  * @param dst Destination of the link. Can be any string depending on the link handler
199  * in the parsing @ref gui2::rich_label.
200  *
201  * @note Special formatting characters in the input are not escaped.
202  * If such behavior is needed, it must be handled by the caller.
203  * @see gui2::rich_label for details on how this tag is parsed.
204  */
205 std::string make_link(const std::string& text, const std::string& dst);
206 
207 //
208 // Markup Parser
209 //
210 
211 /** Thrown when the help system fails to parse something. */
212 struct parse_error : public game::error
213 {
214  parse_error(const std::string& msg) : game::error(msg) {}
215 };
216 
217 /**
218  * Parse a xml style marked up text string. Return a config with the different parts of the
219  * text. Each markup item is a separate part while the text between
220  * markups are separate parts.
221  */
222 config parse_text(const std::string &text);
223 
224 } // namespace markup
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
std::ostringstream wrapper.
Definition: formatter.hpp:40
std::vector< std::pair< std::string_view, std::string_view > > tag_attributes
Definition: markup.hpp:53
std::string italic(Args &&... data)
Applies italic Pango markup to the input.
Definition: markup.hpp:176
std::string span_attribute(std::string_view key, const Value &value, Args &&... data)
Wraps the given data in a span tag with the specified attribute and value.
Definition: markup.hpp:92
std::string img(const std::string &src, const std::string &align, bool floating)
Generates a Help markup tag corresponding to an image.
Definition: markup.cpp:31
std::string make_link(const std::string &text, const std::string &dst)
Generates a Help markup tag corresponding to a reference or link.
Definition: markup.cpp:25
std::string bold(Args &&... data)
Applies bold Pango markup to the input.
Definition: markup.hpp:161
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition: markup.hpp:110
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified tag.
Definition: markup.hpp:45
config parse_text(const std::string &text)
Parse a xml style marked up text string.
Definition: markup.cpp:403
std::string span_size(std::string_view size, Args &&... data)
Applies Pango markup to the input specifying its display size.
Definition: markup.hpp:146
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:85
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::string_view data
Definition: picture.cpp:178
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:61
std::string to_hex_string() const
Returns the stored color in rrggbb hex format.
Definition: color.cpp:88
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:29
Thrown when the help system fails to parse something.
Definition: markup.hpp:213
parse_error(const std::string &msg)
Definition: markup.hpp:214