Logo

index : blog

---

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

        
0/**
1 Static html generator & search server.
2 Copyright (C) 2026 dev@ptrace.dev
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>.
16*/
17
18#import "Basic"()(MEMORY_DEBUGGER = MEMORY_DEBUGGER_ENABLED);
19#import "File";
20#import "File_Utilities";
21#import "String";
22#import "Sort";
23#import "Print_Vars";
24#import "POSIX";
25#import "stb_image";
26#import "stb_image_write";
27#import "stb_image_resize";
28
29#import "stringpad";
30#import "htmltemplate";
31#import "cmark-gfm";
32
33re :: #import "uniform";
34
35#load "constants.h";
36#load "../marshal.jai";
37#load "parser.jai";
38#load "replace.jai";
39#load "entries.jai";
40#load "blog.jai";
41#load "pages.jai";
42#load "update.jai";
43
44
45/** This projects uses the convention of 'header' files. Which are unusual for Jai.
46 But since we have more than one program in the same project, it is easier to
47 share structs and constants.
48
49 The important bit is, that only indepentend objects can live there, with no
50 reference to the other program. Every header file must be self-contained.
51
52 Example:
53
54 This is fine to include.
55
56 Foo :: struct {
57 a, b: int;
58 }
59
60
61 This is bad to include.
62
63 Foo :: struct {
64 a: int;
65 b: My_Custom_Type;
66 }
67
68 Except you include `My_Custom_Type` too, which has no other dependencies!
69
70*/
71
72
73/** About memory: The current memory footprint is very small.
74 Like ~0.2 MB RAM leaked, while processing ~0.3 MB of HTML documents.
75
76 I do not expect to ever reach high numbers, so we can make use of the OS GC.
77*/
78
79
80/** TODO: The deployment to prod of blog posts and binary changes is quite annoying.
81 Need a more streamlined approach so we have less friction.
82
83 There are two workflows.
84
85 1. Deploy posts
86 - Generate site: jai build.jai - run silent gen
87 - Refresh search index: jai build.jai - run silent search :: store
88 - Deploy: dev/push.py prod
89
90 2. Change something on the page
91 - Generate site: jai build.jai - run silent gen
92 - Refresh search index: jai build.jai - run silent search :: store
93 - Rebuild index binary: jai build.jai - silent search release
94 - Deploy: dev/push.py exe
95 dev/push.py prod
96
97 - SSH into server: service.sh restart
98
99*/
100
101
102nav_bar: [..]Navbar_Item;
103pages: [..]Page;
104pages_generated: [..]string;
105
106
107main :: () {
108 #if MEMORY_DEBUGGER_ENABLED defer report_memory_leaks();
109
110 args := get_command_line_arguments();
111
112 if arg_find("help", "-h", "-help", "--help", "?") {
113 log(ARGS_HELP);
114 return;
115 }
116
117 defer print("\n");
118
119 create_project_directories();
120
121
122 /** Update headers */
123 posts_to_update := posts_open(DIR_POSTS);
124 update_metadata_in_posts(posts_to_update);
125
126 generic_pages_to_update := posts_open(DIR_GENERIC);
127 update_metadata_in_posts(generic_pages_to_update);
128
129
130 /** Generate files */
131 posts := posts_open(DIR_POSTS);
132 entries := entries_make(posts);
133 entries_raw_md := array_copy(entries);
134
135 annotations_filter(*entries);
136 markdown_generate(*entries);
137
138
139 /** 2026.04.05
140
141 Currently, `entries_sorted_by_published` is not really used - except in
142 `page_entries_to_disk` where the order does not matter.
143
144 We might need it laterâ„¢
145 */
146
147 entries_sorted_by_update,
148 entries_sorted_by_published
149 := entries_sort(entries);
150
151 rss := page_rss(entries_sorted_by_update);
152
153 html_sorted_by_update_diet, // aka no images supplied, only links
154 html_sorted_by_published
155 := entries_make_html(entries_sorted_by_update, entries_sorted_by_published);
156
157 page_entries_to_disk(entries_sorted_by_published, html_sorted_by_published);
158 page_entries(html_sorted_by_update_diet);
159 page_entries_limited(html_sorted_by_update_diet);
160 page_overview(html_sorted_by_update_diet);
161 page_overview_limited(html_sorted_by_update_diet);
162
163 page_privacy();
164 page_search();
165 page_search_for_server();
166
167
168 /** If any operation above fails, it will exit and not write to file. */
169 entries_dump_data_or_exit(entries_raw_md, FP_DUMP_ENTRIES_MD);
170 entries_dump_data_or_exit(entries, FP_DUMP_ENTRIES_HTML);
171 copy_files_from_to(FILES_TO_COPY);
172 generate_rss(rss);
173 generate_pages();
174
175 if !pages_generated log("No pages generated.");
176 for pages_generated log("> Generated: %", it);
177}
178
179
180
181#scope_file
182
183
184ARGS_HELP :: #string STR_END
185Options:
186 -h, --help This help menu.
187STR_END;
188
189
190
191arg_find :: (words: ..string) -> bool #expand {
192 for words if array_find(`args, it) return true;
193 return false;
194}
195
196
Copyright 2026  E766CB298A6D1E64 | Git-Thing heavily inspired by cgit