Logo

index : blog

---

  • summary
  • about
  • tree
  • log
  • branches
<< path: root/public/blog.git/html/src/gen/entries.jai blob: 033ee430ba3779349f343d13ef9afe2f4f21e196 [raw] [clear marker]

        
0
1
2entries_sort :: (entries: [..]Entry) -> (by_update: []Entry, by_published: []Entry) {
3 sorted_by_update_time := entries_sorted_by(.UPDATED, entries);
4 sorted_by_publish_time := entries_sorted_by(.PUBLISHED, entries);
5 return sorted_by_update_time, sorted_by_publish_time;
6}
7
8entries_make_html :: (by_update: []Entry, by_published: []Entry)
9 -> by_update_diet: [..][]string, by_published: [..][]string
10{
11 make_html :: (sorted: []Entry, dont_show_images: bool) -> [..][]string {
12 temp: [..][]string;
13 for sorted {
14 cal_published := to_calendar(it.published);
15 cal_updated := to_calendar(it.updated);
16
17 /** Note: It's not optimal to propagate `dont_show_images` in that way
18 and create multiple versions of the html. If this is an issue
19 at some point, we need an better idea.
20 */
21 post := replace_tags(it.uri, it.post, dont_show_images);
22
23 entry: [ENTRIES_MAX_FIELDS]string;
24 entry[0] = it.title;
25 entry[1] = post;
26 entry[2] = make_date(cal_published);
27 entry[3] = make_date(cal_updated);
28 entry[4] = it.uri;
29
30 array_add(*temp, array_copy(entry));
31 }
32 return temp;
33 }
34
35 update_diet := make_html(by_update, true);
36 published := make_html(by_published, false);
37
38 return update_diet, published;
39}
40
41entries_make :: (posts: [..]Markdown_File) -> [..]Entry {
42 if !posts {
43 log_error("There are no posts.");
44 exit(1);
45 }
46
47 rendered: [..]Entry;
48
49 for posts {
50 entry: Entry;
51 metadata, post := entries_make_header_and_body(it.content);
52
53 should_skip := entries_parse_metadata(*entry, metadata);
54 if should_skip continue;
55
56 entry.post = post;
57 entry.uri = make_url(entry.published);
58 array_add(*rendered, entry);
59 }
60
61 return rendered;
62}
63
64entries_make_header_and_body :: (post: string) -> (header: string, body: string) {
65 max_preview_count :: 255;
66
67 if !contains(post, METADATA_MARKER) {
68 log_error(
69 "Entry has no metadata marker. Preview:\n% ...",
70 slice(post, 0, max_preview_count)
71 );
72 exit(1);
73 }
74
75 splitted := split(post, METADATA_MARKER);
76
77 if splitted.count != 2 {
78 log_error(
79 "Couldn't create header and body in post. Preview:\n%",
80 slice(post, 0, max_preview_count)
81 );
82 exit(1);
83 }
84
85 metadata := splitted[0];
86 body := splitted[1];
87 body_trimmed := trim(body);
88
89 return metadata, body_trimmed;
90}
91
92entries_parse_metadata :: (entry: *Entry, metadata: string) -> skip: bool {
93
94 invalid_field_error_and_exit :: (metadata: string, s: string) {
95 log_error("Field is invalid: '%'\n---\n%", s, metadata);
96 exit(1);
97 }
98
99 to_apollo_time_or_exit :: (metadata: string, digits: string) -> Apollo_Time {
100 if !is_correct_field_date_format(digits)
101 then invalid_field_error_and_exit(metadata, digits);
102
103 left := find_index_from_left(digits, "(");
104 right := find_index_from_left(digits, ")");
105 if left == -1 || right == -1 then invalid_field_error_and_exit(metadata, digits);
106
107 left += 1;
108 length := right - left;
109
110 value := slice(digits, left, length);
111 time := parse_to_int(value, s64);
112 return milliseconds_to_apollo(time);
113 }
114
115 dispatch_metadata :: (entry: *Entry, metadata: string, m: string, id: int) {
116 match := find_index_from_left(metadata, m);
117 if match == -1 return; // Note: Maybe handling?
118
119 value := parser_consume_till(match + m.count, metadata, #char "\n");
120 trimmed := trim(value, " \r\n\t");
121
122 if id == {
123 case 0; entry.title = trimmed;
124 case 1; entry.width = trimmed;
125 case 2; entry.published = to_apollo_time_or_exit(metadata, trimmed);
126 case 3; entry.updated = to_apollo_time_or_exit(metadata, trimmed);
127 }
128 }
129
130 hidden_tag, remainder := contains_nocase(metadata, "hidden:");
131 if hidden_tag {
132 trimmed := trim_left(remainder);
133 if begins_with_nocase(trimmed, "true") return true;
134 }
135
136 for KEYWORDS dispatch_metadata(entry, metadata, it, it_index);
137
138 return false;
139}
140
141entries_sorted_by :: ($mode: enum { PUBLISHED; UPDATED; }, entries: [..]Entry) -> []Entry {
142
143 compare_by_updated :: (a: Entry, b: Entry) -> s64 {
144 aa := a.updated;
145 bb := b.updated;
146 return compare_apollo_times(bb, aa);
147 }
148
149 compare_by_published :: (a: Entry, b: Entry) -> s64 {
150 aa := a.published;
151 bb := b.published;
152 return compare_apollo_times(bb, aa);
153 }
154
155 // quick_sort sorts in-place
156 entries_local := array_copy(entries);
157
158 #if mode == {
159 case .PUBLISHED; sorted := quick_sort(entries_local, compare_by_published);
160 case .UPDATED; sorted := quick_sort(entries_local, compare_by_updated);
161 }
162
163 return array_copy(sorted);
164}
165
166entries_dump_data_or_exit :: (entries: []Entry, dest: string) {
167 copy := array_copy(entries); // TODO: do we really need a copy? Why?
168 ok := marshal_and_save_to_disk(dest, *copy);
169 if !ok then exit(1);
170}
171
172entry_make :: (post: string) -> Entry {
173 entry: Entry;
174 metadata, post := entries_make_header_and_body(post);
175 entries_parse_metadata(*entry, metadata);
176 entry.post = post;
177 entry.uri = make_url(entry.published);
178 return entry;
179}
180
181
182#scope_file
183
184
185#load "entries.h";
186
187
Copyright 2026  E766CB298A6D1E64 | Git-Thing heavily inspired by cgit