Skip to content

Commit 3bafa13

Browse files
committed
vaev-driver: Properly resolve relative urls.
1 parent d932101 commit 3bafa13

File tree

13 files changed

+98
-49
lines changed

13 files changed

+98
-49
lines changed

src/impls/impl-posix/pkg.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ Res<Vec<String>> installedBundles() {
99
auto [repo, format] = try$(Posix::repoRoot());
1010
Mime::Url repoRoot;
1111
if (format == Posix::RepoType::CUTEKIT) {
12-
repoRoot = try$(Mime::parseUrlOrPath(repo));
12+
repoRoot = Mime::parseUrlOrPath(repo);
1313
} else if (format == Posix::RepoType::PREFIX) {
14-
repoRoot = try$(Mime::parseUrlOrPath(repo))
14+
repoRoot = Mime::parseUrlOrPath(repo)
1515
.join("share");
1616
} else {
1717
return Error::notFound("unknown repo type");

src/libs/karm-mime/path.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,8 @@ Str Path::basename() const {
6969
}
7070

7171
Path Path::join(Path const& other) const {
72-
if (other.rooted) {
72+
if (other.rooted)
7373
return other;
74-
}
7574

7675
Path path = *this;
7776
path._parts.pushBack(other._parts);

src/libs/karm-mime/url.cpp

+23-11
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,21 @@ static auto const RE_COMPONENT =
1111
Re::alnum() | '+'_re | '-'_re | '.'_re
1212
);
1313

14-
Url Url::parse(Io::SScan& s) {
14+
static auto const RE_SCHEME = RE_COMPONENT & ':'_re;
15+
16+
Url Url::parse(Io::SScan& s, Opt<Url> origin) {
1517
Url url;
1618

17-
url.scheme = s.token(RE_COMPONENT);
18-
s.skip(':');
19+
if (s.ahead(RE_SCHEME)) {
20+
url.scheme = s.token(RE_COMPONENT);
21+
s.skip(':');
22+
} else if (origin) {
23+
url.scheme = origin->scheme;
24+
url.authority = origin->authority;
25+
url.host = origin->host;
26+
url.port = origin->port;
27+
url.path = origin->path;
28+
}
1929

2030
if (s.skip("//")) {
2131
auto maybeHost = s.token(RE_COMPONENT);
@@ -33,6 +43,8 @@ Url Url::parse(Io::SScan& s) {
3343
}
3444

3545
url.path = Path::parse(s, true);
46+
if (not url.path.rooted and origin)
47+
url.path = origin->path.join(url.path);
3648

3749
if (s.skip('?'))
3850
url.query = s.token(Re::until('#'_re));
@@ -43,9 +55,9 @@ Url Url::parse(Io::SScan& s) {
4355
return url;
4456
}
4557

46-
Url Url::parse(Str str) {
58+
Url Url::parse(Str str, Opt<Url> origin) {
4759
Io::SScan s{str};
48-
return parse(s);
60+
return parse(s, origin);
4961
}
5062

5163
bool Url::isUrl(Str str) {
@@ -116,15 +128,15 @@ String Url::str() const {
116128
return writer.str();
117129
}
118130

119-
Res<Url> parseUrlOrPath(Str str) {
131+
Url parseUrlOrPath(Str str, Opt<Url> origin) {
120132
if (Url::isUrl(str)) {
121-
return Ok(Url::parse(str));
133+
return Url::parse(str, origin);
122134
}
123135

124-
Url url;
125-
url.scheme = "file"s;
126-
url.path = Path::parse(str);
127-
return Ok(url);
136+
Url url = origin.unwrapOr("file:"_url);
137+
url.path = url.path.join(Path::parse(str));
138+
139+
return url;
128140
}
129141

130142
} // namespace Karm::Mime

src/libs/karm-mime/url.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ struct Url {
1818
String query;
1919
String fragment;
2020

21-
static Url parse(Io::SScan& s);
21+
static Url parse(Io::SScan& s, Opt<Url> orgin = NONE);
2222

23-
static Url parse(Str str);
23+
static Url parse(Str str, Opt<Url> orgin = NONE);
2424

2525
static bool isUrl(Str str);
2626

@@ -57,19 +57,19 @@ struct Url {
5757
auto operator<=>(Url const&) const = default;
5858
};
5959

60-
Res<Url> parseUrlOrPath(Str str);
60+
Url parseUrlOrPath(Str str, Opt<Url> origin = NONE);
6161

6262
} // namespace Karm::Mime
6363

64-
inline auto operator""_url(char const* str, usize len) {
64+
inline Mime::Url operator""_url(char const* str, usize len) {
6565
return Karm::Mime::Url::parse({str, len});
6666
}
6767

68-
inline auto operator/(Karm::Mime::Url const& url, Str path) {
68+
inline Mime::Url operator/(Karm::Mime::Url const& url, Str path) {
6969
return url.join(path);
7070
}
7171

72-
inline auto operator/(Karm::Mime::Url const& url, Karm::Mime::Path const& path) {
72+
inline Mime::Url operator/(Karm::Mime::Url const& url, Karm::Mime::Path const& path) {
7373
return url.join(path);
7474
}
7575

src/libs/karm-text/cli/main.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Async::Task<> entryPointAsync(Sys::Context& ctx) {
6565
if (args.len() != 2)
6666
co_return Error::invalidInput("Usage: karm-text.cli dump-ttf <url>");
6767

68-
auto url = co_try$(Mime::parseUrlOrPath(args[1]));
68+
auto url = Mime::parseUrlOrPath(args[1]);
6969
auto file = co_try$(Sys::File::open(url));
7070
auto map = co_try$(Sys::mmap().map(file));
7171
auto ttf = co_try$(Ttf::Parser::init(map.bytes()));
@@ -83,7 +83,7 @@ Async::Task<> entryPointAsync(Sys::Context& ctx) {
8383
if (args.len() != 2)
8484
co_return Error::invalidInput("Usage: karm-text.cli dump-attr <url>");
8585

86-
auto url = co_try$(Mime::parseUrlOrPath(args[1]));
86+
auto url = Mime::parseUrlOrPath(args[1]);
8787
auto font = co_try$(Text::loadFontface(url));
8888

8989
Sys::println("{}", font->attrs());

src/main.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,10 @@ Async::Task<> entryPointAsync(Sys::Context& ctx) {
230230
Mime::Url outputUrl = "fd:stdout"_url;
231231

232232
if (inputArg.unwrap() != "-"s)
233-
inputUrl = co_try$(Mime::parseUrlOrPath(inputArg));
233+
inputUrl = Mime::parseUrlOrPath(inputArg);
234234

235235
if (outputArg.unwrap() != "-"s)
236-
outputUrl = co_try$(Mime::parseUrlOrPath(outputArg));
236+
outputUrl = Mime::parseUrlOrPath(outputArg);
237237

238238
if (outputMimeArg.unwrap() != ""s)
239239
options.outputFormat = co_try$(Mime::Uti::fromMime(Mime::Mime{outputMimeArg}));
@@ -277,10 +277,10 @@ Async::Task<> entryPointAsync(Sys::Context& ctx) {
277277
Mime::Url outputUrl = "fd:stdout"_url;
278278

279279
if (inputArg.unwrap() != "-"s)
280-
inputUrl = co_try$(Mime::parseUrlOrPath(inputArg));
280+
inputUrl = Mime::parseUrlOrPath(inputArg);
281281

282282
if (outputArg.unwrap() != "-"s)
283-
outputUrl = co_try$(Mime::parseUrlOrPath(outputArg));
283+
outputUrl = Mime::parseUrlOrPath(outputArg);
284284

285285
if (outputMimeArg.unwrap() != ""s)
286286
options.outputFormat = co_try$(Mime::Uti::fromMime(Mime::Mime{outputMimeArg}));

src/web/vaev-browser/main/main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Vaev.Browser;
77
Async::Task<> entryPointAsync(Sys::Context& ctx) {
88
auto args = Sys::useArgs(ctx);
99
auto url = args.len()
10-
? co_try$(Mime::parseUrlOrPath(args[0]))
10+
? Mime::parseUrlOrPath(args[0])
1111
: "about:start"_url;
1212
Gc::Heap heap;
1313
Vaev::Driver::FileFetcher fetcher;

src/web/vaev-dom/_forward.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
namespace Vaev::Dom {
4+
5+
struct Node;
6+
struct Document;
7+
struct Element;
8+
9+
} // namespace Vaev::Dom

src/web/vaev-dom/node.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "node.h"
2+
3+
#include "document.h"
4+
5+
namespace Vaev::Dom {
6+
7+
// https://dom.spec.whatwg.org/#ref-for-dom-node-baseuri%E2%91%A0
8+
Mime::Url Node::baseURI() {
9+
auto document = ownerDocument();
10+
if (not document)
11+
panic("node has no owner document");
12+
return document->url().parent(1);
13+
}
14+
15+
// https://dom.spec.whatwg.org/#ref-for-dom-node-ownerdocument%E2%91%A0
16+
Gc::Ptr<Document> Node::ownerDocument() {
17+
for (auto curr = parentNode(); curr; curr = curr->parentNode())
18+
if (auto doc = curr->is<Document>())
19+
return *doc;
20+
return nullptr;
21+
}
22+
23+
void Node::repr(Io::Emit& e) const {
24+
e("({}", nodeType());
25+
_repr(e);
26+
if (hasChildren()) {
27+
e.indentNewline();
28+
for (auto child = firstChild(); child->hasNextSibling(); child = child->nextSibling())
29+
child->repr(e);
30+
e.deindent();
31+
}
32+
e(")\n");
33+
}
34+
35+
} // namespace Vaev::Dom

src/web/vaev-dom/node.h

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#pragma once
22

3+
#include <karm-mime/url.h>
4+
5+
#include "_forward.h"
36
#include "tree.h"
47

58
namespace Vaev::Dom {
@@ -41,19 +44,13 @@ struct Node : public Tree<Node> {
4144
return static_cast<T const*>(this);
4245
}
4346

47+
Mime::Url baseURI();
48+
49+
Gc::Ptr<Document> ownerDocument();
50+
4451
virtual void _repr(Io::Emit&) const {}
4552

46-
void repr(Io::Emit& e) const {
47-
e("({}", nodeType());
48-
_repr(e);
49-
if (hasChildren()) {
50-
e.indentNewline();
51-
for (auto child = firstChild(); child->hasNextSibling(); child = child->nextSibling())
52-
child->repr(e);
53-
e.deindent();
54-
}
55-
e(")\n");
56-
}
53+
void repr(Io::Emit& e) const;
5754

5855
bool operator==(Node const& other) const {
5956
return this == &other;

src/web/vaev-driver/fetcher.cpp

+3-8
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,10 @@ void fetchStylesheets(Fetcher& fetcher, Gc::Ref<Dom::Node> node, Style::StyleBoo
142142
return;
143143
}
144144

145-
auto url = Mime::parseUrlOrPath(*href);
146-
if (not url) {
147-
logWarn("link element href attribute is not a valid URL: {}", *href);
148-
return;
149-
}
150-
151-
auto sheet = fetchStylesheet(fetcher, url.take(), Style::Origin::AUTHOR);
145+
auto url = Mime::parseUrlOrPath(*href, node->baseURI());
146+
auto sheet = fetchStylesheet(fetcher, url, Style::Origin::AUTHOR);
152147
if (not sheet) {
153-
logWarn("failed to fetch stylesheet: {}", sheet);
148+
logWarn("failed to fetch stylesheet from {}: {}", url, sheet);
154149
return;
155150
}
156151

src/web/vaev-driver/res/missing.qoi

498 Bytes
Binary file not shown.

src/web/vaev-layout/builder.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,10 @@ static void _buildImage(Style::Computer& c, Gc::Ref<Dom::Element> el, Box& paren
201201
auto font = _lookupFontface(*style);
202202

203203
auto src = el->getAttribute(Html::SRC_ATTR).unwrapOr(""s);
204-
auto url = Mime::Url::parse(src);
205-
auto img = Karm::Image::loadOrFallback(url).unwrap();
204+
auto url = Mime::parseUrlOrPath(src, el->baseURI());
205+
auto img = Karm::Image::load(url).unwrapOrElse([] {
206+
return Karm::Image::loadOrFallback("bundle://vaev-driver/missing.qoi"_url).unwrap();
207+
});
206208
parent.add({style, font, img});
207209
}
208210

0 commit comments

Comments
 (0)