RunicVTT Open Source Virtual Tabletop for TTRPG using P2P
Loading...
Searching...
No Matches
MarkdownRenderer.cpp
Go to the documentation of this file.
1#include "MarkdownRenderer.h"
2
3#define WIN32_LEAN_AND_MEAN
4#include <windows.h>
5#include <shellapi.h>
6
7// ---------- imgui_md override ----------
9{
10 const auto a = parseHref_(m_href);
11 switch (a.kind)
12 {
15 onOpenExternal(a.payload);
16 break;
17
19 if (onRoll)
20 onRoll(a.payload);
21 break;
22
24 {
25 std::string uuid = resolveNote_(a.payload);
26 if (!uuid.empty() && onNoteOpen)
27 onNoteOpen(uuid);
28 break;
29 }
30
31 default:
32 // Fallback: try external open if handler present
34 onOpenExternal(m_href);
35 else
36 openDefaultBrowser_(m_href);
37 break;
38 }
39}
40
42{
43 // Turn Markdown soft-breaks into visible line breaks.
44 // Either of these works; TextUnformatted("\n") is a common pattern with imgui_md.
45 ImGui::TextUnformatted("\n");
46 // Alternatively:
47 // ImGui::NewLine();
48}
49
50// ---------- parse / resolve ----------
52{
53 // external?
54 if (startsWith_(href, "http://") || startsWith_(href, "https://"))
55 return {Action::OpenExternal, href};
56
57 // roll://expr or roll:expr
58 if (startsWith_(href, "roll://"))
59 return {Action::RollExpr, href.substr(7)};
60 if (startsWith_(href, "roll:"))
61 return {Action::RollExpr, href.substr(5)};
62
63 // note://open/<ref>
64 if (startsWith_(href, "note://open/"))
65 return {Action::NoteOpen, href.substr(std::string("note://open/").size())};
66
67 // Short forms: note:/<ref> / note:<ref>
68 if (startsWith_(href, "note:/"))
69 return {Action::NoteOpen, href.substr(6)};
70 if (startsWith_(href, "note:"))
71 return {Action::NoteOpen, href.substr(5)};
72
73 return {};
74}
75
76std::string MarkdownRenderer::resolveNote_(const std::string& ref) const
77{
78 if (looksLikeUuid_(ref))
79 return ref;
80
82 return resolveNoteRef(ref);
83
84 return {};
85}
86
87// ---------- platform opener ----------
88void MarkdownRenderer::openDefaultBrowser_(const std::string& url)
89{
90 if (url.empty())
91 return;
92
93 // Use wide API for unicode URLs
94 int wlen = MultiByteToWideChar(CP_UTF8, 0, url.c_str(), -1, nullptr, 0);
95 std::wstring wurl;
96 wurl.resize(wlen ? (wlen - 1) : 0);
97 if (wlen > 0)
98 MultiByteToWideChar(CP_UTF8, 0, url.c_str(), -1, wurl.data(), wlen);
99
100 HINSTANCE r = ShellExecuteW(nullptr, L"open", wurl.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
101 if ((INT_PTR)r <= 32)
102 {
103 // Very dumb fallback
104 std::string cmd = "start \"\" \"" + url + "\"";
105 std::system(cmd.c_str());
106 }
107}
108
109// ---------- small helpers ----------
110bool MarkdownRenderer::startsWith_(const std::string& s, const char* pref)
111{
112 const size_t n = std::strlen(pref);
113 return s.size() >= n && std::equal(pref, pref + n, s.begin());
114}
115
116bool MarkdownRenderer::looksLikeUuid_(const std::string& s)
117{
118 if (s.size() != 36)
119 return false;
120 const int dashPos[4] = {8, 13, 18, 23};
121 for (int i = 0; i < 36; ++i)
122 {
123 if (i == dashPos[0] || i == dashPos[1] || i == dashPos[2] || i == dashPos[3])
124 {
125 if (s[i] != '-')
126 return false;
127 }
128 else if (!isHex_(s[i]))
129 {
130 return false;
131 }
132 }
133 return true;
134}
135
136bool MarkdownRenderer::looksLikeShortId_(const std::string& s)
137{
138 if (s.size() < 8)
139 return false;
140 for (char c : s)
141 {
142 if (c == '-')
143 return false;
144 if (!isHex_(c))
145 return false;
146 }
147 return true;
148}
149
151{
152 return std::isxdigit(static_cast<unsigned char>(c)) != 0;
153}
static bool startsWith_(const std::string &s, const char *pref)
static void openDefaultBrowser_(const std::string &url)
std::function< std::string(const std::string &ref) resolveNoteRef)
void open_url() const override
std::string resolveNote_(const std::string &ref) const
std::function< void(const std::string &expr) onRoll)
static bool isHex_(char c)
std::function< void(const std::string &url) onOpenExternal)
std::function< void(const std::string &uuid) onNoteOpen)
static bool looksLikeShortId_(const std::string &s)
void soft_break() override
Parsed parseHref_(const std::string &href) const
static bool looksLikeUuid_(const std::string &s)