Skip to content

Commit 1f3aa95

Browse files
committed
goodies
- new `auto_target_blank` setting in zine.ziggy, now external links don't default to target blank anymore, use this setting to restore the previous behavior - remove the ability to pass arguments to `$site.pages()` - add the ability to pass multiple arguments to `$site.page()` in order to create parametrized paths - add `$page.leaves()` to obtain a flat list of leaf pages from a given section subtree - update superhtml scripty reference docs syntax to better match the new syntax in Ziggy Schemas
1 parent 7abc521 commit 1f3aa95

19 files changed

Lines changed: 513 additions & 165 deletions

File tree

build.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,12 @@ pub fn build(b: *std.Build) !void {
265265
switch (version) {
266266
.tag, .preview => {
267267
const zon = @import("build.zig.zon");
268-
if (version == .preview or std.mem.eql(u8, zon.version, version.tag[1..])) {
268+
if (version == .preview or std.mem.eql(u8, zon.version, version.tag)) {
269269
setupReleaseStep(b, release, version.string(), translate_c);
270270
} else {
271271
release.dependOn(&b.addFail(b.fmt(
272272
"error: git tag does not match zon package version (zon: '{s}', git: '{s}')",
273-
.{ zon.version, version.tag[1..] },
273+
.{ zon.version, version.tag },
274274
)).step);
275275
}
276276
},

build.zig.zon

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@
3838
.hash = "zeit-0.10.0-dev-5I6bk3m9AgB8Ndev81pibV70MJe9VCOXAGZBNU833c4Y",
3939
},
4040
.flow_syntax = .{
41-
.url = "git+https://github.com/neurocyte/flow-syntax#65e76b959b9ac7c2aab8aba0d7decc5a3f04e4e1",
42-
.hash = "flow_syntax-0.7.2-X8jOoQlmAQA3iLvWcCZZr1sYEEiBpHqi8VWqweKwwxGB",
41+
.url = "git+https://github.com/kristoff-it/flow-syntax#b42c3e985215e88a8faa260cbf7eb248822c339c",
42+
.hash = "flow_syntax-0.7.2-X8jOoSuMAQBanH2g5oW4BQmkW6s5AdfrRUE2byWrMVKp",
4343
},
4444
.ziggy = .{
45-
.url = "git+https://github.com/kristoff-it/ziggy#35ed5530dd93590fa40e06005ec5d7747a5498d5",
45+
.url = "git+https://github.com/kristoff-it/ziggy#7b81a7f1c9e6b22aacd7060b17bb6b7142878cd8",
4646
.hash = "ziggy-0.1.0-kTg8vxOeBwCS6RxeI2quMQ7PCnCSWWB3Q-NF-JOktWrN",
4747
},
4848
.supermd = .{
49-
.url = "git+https://github.com/kristoff-it/supermd#cbca93e22ca8c92a8c570b649a38f57242e00635",
50-
.hash = "supermd-0.1.0-3Mco3BecWABhO5BJzBZrz9lf8SeoeLpz4wQkFmJqcN7d",
49+
.url = "git+https://github.com/kristoff-it/supermd#70e34739939e927dcef97288b57d30b24d221497",
50+
.hash = "supermd-0.1.0-3Mco3GGbWACu_iiyO6xjVV1ViSYFACf2f_TIwjjJmEw9",
5151
},
5252
.translate_c = .{
5353
.url = "git+https://codeberg.org/kristoff/translate-c?ref=0.17.x#c01b34d1e57010019d77ffef1dbc704af870a2eb",

src/Variant.zig

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,22 @@ pub const Section = struct {
105105
content_sub_path: Path,
106106
parent_section: u32, // index into sections, 0 = no parent section
107107
index: u32, // index into pages
108-
pages: std.ArrayListUnmanaged(u32) = .empty, // indices into pages
108+
pages: std.ArrayList(u32) = .empty, // indices into pages
109+
pages_by_author: std.StringHashMapUnmanaged([]const u32) = .empty, // indices into pages
110+
pages_by_tag: std.StringHashMapUnmanaged([]const u32) = .empty, // indices into pages
109111

110112
pub fn deinit(s: *const Section, gpa: Allocator) void {
113+
var p = s.pages;
114+
p.deinit(gpa);
115+
{
116+
var it = s.pages_by_author.iterator();
117+
while (it.next()) |entry| gpa.free(entry.value_ptr.*);
118+
@constCast(s).pages_by_author.deinit(gpa);
119+
}
111120
{
112-
var p = s.pages;
113-
p.deinit(gpa);
121+
var it = s.pages_by_tag.iterator();
122+
while (it.next()) |entry| gpa.free(entry.value_ptr.*);
123+
@constCast(s).pages_by_tag.deinit(gpa);
114124
}
115125
}
116126

@@ -129,8 +139,10 @@ pub const Section = struct {
129139
s.active = index._parse.active;
130140
}
131141

132-
pub fn sortPages(
142+
pub fn indexAndSortPages(
133143
s: *Section,
144+
gpa: Allocator,
145+
arena: Allocator,
134146
v: *Variant,
135147
pages: []Page,
136148
) void {
@@ -167,7 +179,39 @@ pub const Section = struct {
167179
};
168180

169181
const ctx: Ctx = .{ .pages = pages, .v = v };
170-
std.sort.insertion(u32, s.pages.items, ctx, Ctx.lessThan);
182+
std.sort.pdq(u32, s.pages.items, ctx, Ctx.lessThan);
183+
184+
var author_temp: std.StringArrayHashMapUnmanaged(std.ArrayList(u32)) = .empty;
185+
var tag_temp: std.StringArrayHashMapUnmanaged(std.ArrayList(u32)) = .empty;
186+
for (s.pages.items) |idx| {
187+
const p = pages[idx];
188+
if (!p._parse.active) continue;
189+
190+
// TODO: report errors when a page has the same author listed twice
191+
for (p.authors) |key| {
192+
const gop = author_temp.getOrPut(arena, key) catch fatal.oom();
193+
if (!gop.found_existing) gop.value_ptr.* = .empty;
194+
gop.value_ptr.append(gpa, idx) catch fatal.oom();
195+
}
196+
197+
// TODO: report errors when a page has the same tag listed twice
198+
for (p.tags) |key| {
199+
const gop = tag_temp.getOrPut(arena, key) catch fatal.oom();
200+
if (!gop.found_existing) gop.value_ptr.* = .empty;
201+
gop.value_ptr.append(gpa, idx) catch fatal.oom();
202+
}
203+
}
204+
205+
s.pages_by_author.ensureTotalCapacity(gpa, @intCast(author_temp.count())) catch fatal.oom();
206+
s.pages_by_tag.ensureTotalCapacity(gpa, @intCast(tag_temp.count())) catch fatal.oom();
207+
208+
for (author_temp.keys(), author_temp.values()) |key, *val| {
209+
s.pages_by_author.putAssumeCapacityNoClobber(key, val.toOwnedSlice(gpa) catch fatal.oom());
210+
}
211+
212+
for (tag_temp.keys(), tag_temp.values()) |key, *val| {
213+
s.pages_by_tag.putAssumeCapacityNoClobber(key, val.toOwnedSlice(gpa) catch fatal.oom());
214+
}
171215
}
172216
};
173217

src/context/DateTime.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const Value = context.Value;
1212
const String = context.String;
1313
const Bool = context.Bool;
1414

15-
const epoch = zeit.instant(.{ .unix_timestamp = 0 }, &zeit.utc);
15+
pub const epoch = zeit.instant(.{ .unix_timestamp = 0 }, &zeit.utc);
1616

1717
_raw: ?Raw = null,
1818
_loc: ?ziggy.Tokenizer.Token.Loc = null,

src/context/Iterator.zig

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
const Iterator = @This();
22

33
const std = @import("std");
4+
const assert = std.debug.assert;
45
const ziggy = @import("ziggy");
56
const superhtml = @import("superhtml");
67
const scripty = @import("scripty");
8+
const zeit = @import("zeit");
79
const context = @import("../context.zig");
810
const doctypes = @import("doctypes.zig");
911
const Signature = doctypes.Signature;
@@ -25,7 +27,8 @@ _superhtml_context: superhtml.utils.IteratorContext(Value) = .{},
2527
_impl: Impl,
2628

2729
pub const Impl = union(enum) {
28-
value_it: SliceIterator(Value),
30+
slice_it: SliceIterator(Value),
31+
leaves_it: LeavesIterator,
2932

3033
pub fn len(impl: Impl) usize {
3134
switch (impl) {
@@ -37,6 +40,7 @@ pub const Impl = union(enum) {
3740
pub fn init(gpa: Allocator, impl: Impl) !*Iterator {
3841
const res = try gpa.create(Iterator);
3942
res.* = .{ ._impl = impl, .len = impl.len() };
43+
res.last = 0 == res.len;
4044
return res;
4145
}
4246

@@ -45,21 +49,24 @@ pub fn deinit(iter: *const Iterator, gpa: Allocator) void {
4549
}
4650

4751
pub fn next(iter: *Iterator, gpa: Allocator) !bool {
52+
if (iter.last) return false;
53+
4854
switch (iter._impl) {
4955
inline else => |*v| {
50-
const item = try v.next(gpa);
51-
iter.it = try Value.from(gpa, item orelse return false);
52-
iter.idx += 1;
53-
iter.first = iter.idx == 1;
54-
iter.last = iter.idx == iter.len;
55-
return true;
56+
const item = try v.next(iter.idx, gpa);
57+
iter.it = try Value.from(gpa, item);
5658
},
5759
}
60+
61+
iter.idx += 1;
62+
iter.first = iter.idx == 1;
63+
iter.last = iter.idx >= iter.len;
64+
return true;
5865
}
5966

6067
pub fn fromArray(gpa: Allocator, arr: Array) !*Iterator {
6168
return init(gpa, .{
62-
.value_it = .{ .items = arr._items },
69+
.slice_it = .{ .items = arr._items },
6370
});
6471
}
6572

@@ -82,6 +89,7 @@ pub const Fields = struct {
8289
\\True on the last iteration loop.
8390
;
8491
};
92+
8593
pub const Builtins = struct {
8694
pub const up = struct {
8795
pub const signature: Signature = .{ .ret = .Iterator };
@@ -107,18 +115,71 @@ pub const Builtins = struct {
107115

108116
fn SliceIterator(comptime Element: type) type {
109117
return struct {
110-
idx: usize = 0,
111118
items: []const Element,
112119

113120
pub fn len(self: @This()) usize {
114121
return self.items.len;
115122
}
116123

117-
pub fn next(self: *@This(), gpa: Allocator) !?Element {
124+
pub fn next(self: *@This(), idx: usize, gpa: Allocator) !Element {
118125
_ = gpa;
119-
if (self.idx == self.items.len) return null;
120-
defer self.idx += 1;
121-
return self.items[self.idx];
126+
return self.items[idx];
122127
}
123128
};
124129
}
130+
131+
pub const LeavesIterator = struct {
132+
limit: u32,
133+
sections: []Section,
134+
pages: []Page,
135+
136+
pub const Section = struct {
137+
idx: u32 = 0, // cursor into `page_indexes`
138+
page_indexes: []const u32, // index into pages
139+
};
140+
141+
pub fn init(limit: u32, sections: []Section, pages: []Page) LeavesIterator {
142+
return .{
143+
.limit = limit,
144+
.sections = sections,
145+
.pages = pages,
146+
};
147+
}
148+
149+
pub fn len(lit: *const LeavesIterator) usize {
150+
return lit.limit;
151+
}
152+
153+
pub fn next(lit: *LeavesIterator, idx: usize, gpa: Allocator) !*context.Page {
154+
assert(idx < lit.limit);
155+
_ = gpa;
156+
157+
var next_page_date = context.DateTime.epoch;
158+
var next_page: *context.Page = undefined;
159+
var next_section_idx: usize = undefined;
160+
161+
for (lit.sections, 0..) |*s, section_idx| {
162+
if (s.idx == s.page_indexes.len) continue;
163+
164+
while (true) {
165+
const page_idx = s.page_indexes[s.idx];
166+
const page = &lit.pages[page_idx];
167+
if (!page._parse.active) {
168+
s.idx += 1;
169+
continue;
170+
}
171+
172+
if (page.date._inst.timestamp >= next_page_date.timestamp) {
173+
next_page_date = page.date._inst;
174+
next_page = page;
175+
next_section_idx = section_idx;
176+
}
177+
178+
break;
179+
}
180+
}
181+
182+
lit.sections[next_section_idx].idx += 1;
183+
return next_page;
184+
}
185+
};

0 commit comments

Comments
 (0)