| 227 | } |
| 228 | |
| 229 | inline std::string HTMLElement::escapeHTMLString (std::string_view text, bool escapeNewLines) |
| 230 | { |
| 231 | std::string result; |
| 232 | result.reserve (text.length()); |
| 233 | |
| 234 | for (auto character : text) |
| 235 | { |
| 236 | auto unicodeChar = static_cast<uint32_t> (character); |
| 237 | |
| 238 | auto isCharLegal = +[] (uint32_t c) -> bool |
| 239 | { |
| 240 | return (c >= 'a' && c <= 'z') |
| 241 | || (c >= 'A' && c <= 'Z') |
| 242 | || (c >= '0' && c <= '9') |
| 243 | || (c < 127 && std::string_view (" .,;:-()_+=?!$#@[]/|*%~{}\\").find ((char) c) != std::string_view::npos); |
| 244 | }; |
| 245 | |
| 246 | if (isCharLegal (unicodeChar)) |
| 247 | { |
| 248 | result += character; |
| 249 | } |
| 250 | else |
| 251 | { |
| 252 | switch (unicodeChar) |
| 253 | { |
| 254 | case '<': result += "<"; break; |
| 255 | case '>': result += ">"; break; |
| 256 | case '&': result += "&"; break; |
| 257 | case '"': result += """; break; |
| 258 | |
| 259 | default: |
| 260 | if (! escapeNewLines && (unicodeChar == '\n' || unicodeChar == '\r')) |
| 261 | result += character; |
| 262 | else |
| 263 | result += "&#" + std::to_string (unicodeChar) + ';'; |
| 264 | |
| 265 | break; |
| 266 | } |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | return result; |
| 271 | } |
| 272 | |
| 273 | } // namespace choc::html |
| 274 | |