Skip to content

Commit

Permalink
superhtml: linking facilities for alternatives
Browse files Browse the repository at this point in the history
  • Loading branch information
kristoff-it committed Oct 28, 2024
1 parent 2f0cce7 commit ec0f549
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 16 deletions.
4 changes: 2 additions & 2 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
.version = "0.0.0",
.dependencies = .{
.supermd = .{
.url = "git+https://github.com/kristoff-it/supermd#e6acc6a80c26940f819eda0741ed16c385d7daf4",
.hash = "1220b8f73b279176b97cbe98639b49c1a5f42d5de7d233e67b1c69e5798479f00836",
.url = "git+https://github.com/kristoff-it/supermd#a034ec48c8a01b26de50f479090716d3ed2152c9",
.hash = "122058e6f4ebd493d1c7f7c1e21549d2b2e5d9a1921dba758f3558d88a34a70384be",
},
.scripty = .{
.url = "git+https://github.com/kristoff-it/scripty#df8c11380f9e9bec34809f2242fb116d27cf39d6",
Expand Down
82 changes: 69 additions & 13 deletions src/context/Page.zig
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ pub const Translation = struct {
};

pub const Alternative = struct {
name: []const u8 = "",
name: []const u8,
layout: []const u8,
output: []const u8,
type: []const u8 = "",
_prefix: []const u8 = "",

pub const dot = scripty.defaultDot(Alternative, Value, false);
// pub const PassByRef = true;

pub const Builtins = struct {};
pub const description =
\\An alternative version of the current page. Title and type
\\can be used when generating `<link rel="alternate">` elements.
Expand All @@ -113,7 +113,7 @@ pub const Alternative = struct {
\\Useful for example to generate RSS links:
\\
\\```superhtml
\\<ctx alt="$page.alternative('rss')"
\\<ctx alt="$page.alternative('rss')">
\\ <a href="$ctx.alt.link()"
\\ type="$ctx.alt.type"
\\ :text="$ctx.alt.name"
Expand All @@ -122,6 +122,33 @@ pub const Alternative = struct {
\\```
;
};
pub const Builtins = struct {
pub const link = struct {
pub const signature: Signature = .{ .ret = .String };
pub const description =
\\Returns the URL of the target alternative.
;
pub const examples =
\\$page.alternative("rss").link()
;
pub fn call(
alt: Alternative,
gpa: Allocator,
args: []const Value,
) !Value {
if (args.len != 0) return .{ .err = "expected 0 arguments" };

const result = try join(gpa, &.{
"/",
alt._prefix,
alt.output,
"/",
});

return String.init(result);
}
};
};
};
pub const dot = scripty.defaultDot(Page, Value, false);
pub const PassByRef = true;
Expand Down Expand Up @@ -711,7 +738,10 @@ pub const Builtins = struct {
};

pub const linkRef = struct {
pub const signature: Signature = .{ .ret = .String };
pub const signature: Signature = .{
.params = &.{.String},
.ret = .String,
};
pub const description =
\\Returns the URL of the target page, allowing you
\\to specify a fragment id to deep-link to a specific
Expand Down Expand Up @@ -766,19 +796,45 @@ pub const Builtins = struct {
}
};

// TODO: delete this
pub const permalink = struct {
pub const signature: Signature = .{ .ret = .String };
pub const alternative = struct {
pub const signature: Signature = .{
.params = &.{.String},
.ret = .Alternative,
};
pub const description =
\\Deprecated, use `link()`
\\Returns an alternative by name.
;
pub const examples =
\\<ctx alt="$page.alternative('rss')">
\\ <a href="$ctx.alt.link()"
\\ type="$ctx.alt.type"
\\ :text="$ctx.alt.name"
\\ ></a>
;
pub const examples = "";
pub fn call(
_: *const Page,
_: Allocator,
_: []const Value,
p: *const Page,
gpa: Allocator,
args: []const Value,
) !Value {
return .{ .err = "deprecated, use `link`" };
const bad_arg = .{
.err = "expected 1 string argument",
};
if (args.len != 1) return bad_arg;

const alt_name = switch (args[0]) {
.string => |s| s.value,
else => return bad_arg,
};

for (p.alternatives) |alt| {
if (std.mem.eql(u8, alt.name, alt_name)) {
return Value.from(gpa, alt);
}
}

return .{
.err = "unable to find an alertnative with the provided name",
};
}
};

Expand Down
54 changes: 53 additions & 1 deletion src/exes/layout/cache.zig
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,8 @@ fn loadPage(
.is_root = is_root_page,
};

for (page.alternatives) |*alt| @constCast(alt)._prefix = site._meta.url_path_prefix;

if (page.translation_key) |tk| {
const tk_index_path = try join(gpa, &.{ index_dir_path, "tk", tk });
const tk_index = try std.fs.cwd().readFileAlloc(
Expand Down Expand Up @@ -957,7 +959,33 @@ fn loadPage(
inline else => |val, tag| {
const res = switch (val.src.?) {
.url => continue,
.self_page => context.String.init(""),
.self_page => blk: {
if (@hasField(@TypeOf(val), "alternative")) {
if (val.alternative) |alt_name| {
for (page.alternatives) |alt| {
if (std.mem.eql(u8, alt.name, alt_name)) {
const abs = try join(gpa, &.{
"/",
site._meta.url_path_prefix,
alt.output,
"/",
});
break :blk context.String.init(abs);
}
} else reportError(
n,
md_src,
md_rel_path,
md_path,
fm_offset,
is_section,
"the page has no alternative with this name",
);
}
}
break :blk context.String.init("");
},

.page => |p| blk: {
const page_site = if (p.locale) |lc|
sites.get(lc) orelse reportError(
Expand Down Expand Up @@ -1043,6 +1071,30 @@ fn loadPage(
}
}

if (@hasField(@TypeOf(val), "alternative")) {
if (val.alternative) |alt_name| {
for (pp.alternatives) |alt| {
if (std.mem.eql(u8, alt.name, alt_name)) {
const abs = try join(gpa, &.{
"/",
pp._meta.site._meta.url_path_prefix,
alt.output,
"/",
});
break :blk context.String.init(abs);
}
} else reportError(
n,
md_src,
md_rel_path,
md_path,
fm_offset,
is_section,
"the page has no alternative with this name",
);
}
}

if (page_site == site) {
break :blk try context.Page.Builtins.link.call(
pp,
Expand Down

0 comments on commit ec0f549

Please sign in to comment.