gitlyx / utils.v
232 lines · 209 sloc · 5.09 KB · 31b1cb297e0cd7893d102dbf7410a58b89a2cf54
Raw
1module main
2
3import time
4import math
5import os
6import veb
7
8pub fn (mut app App) running_since() string {
9 duration := time.now().unix() - app.started_at
10
11 seconds_in_hour := 60 * 60
12
13 days := int(math.floor(f64(duration) / f64(seconds_in_hour * 24)))
14 hours := int(math.fmod(math.floor(f64(duration) / f64(seconds_in_hour)), 24))
15 minutes := int(math.floor(f64(duration) / 60.0)) % 60
16 seconds := duration % 60
17
18 return '${days} days ${hours} hours ${minutes} minutes and ${seconds} seconds'
19}
20
21pub fn (mut ctx Context) make_path(branch_name string, i int) string {
22 if i == 0 {
23 return ctx.path_split[..i + 1].join('/')
24 }
25 mut s := ctx.path_split[0]
26 s += '/tree/${branch_name}/'
27 s += ctx.path_split[1..i + 1].join('/')
28 return s
29}
30
31fn create_directory_if_not_exists(path string) {
32 if !os.exists(path) {
33 os.mkdir(path) or { panic('cannot create ${path} directory') }
34 }
35}
36
37fn calculate_pages(count int, per_page int) int {
38 if count == 0 {
39 return 0
40 }
41
42 return int(math.ceil(f32(count) / f32(per_page))) - 1
43}
44
45fn generate_prev_next_pages(page int) (int, int) {
46 prev_page := if page > 0 { page - 1 } else { 0 }
47 next_page := page + 1
48
49 return prev_page, next_page
50}
51
52fn check_first_page(page int) bool {
53 return page == 0
54}
55
56fn check_last_page(total int, offset int, per_page int) bool {
57 return (total - offset) < per_page
58}
59
60const is_dev = true
61
62fn css2(s string) veb.RawHtml {
63 if is_dev {
64 return '<link href="http://localhost:8000/${s}" rel="stylesheet" type="text/css">'
65 } else {
66 return '<link href="/static/${s}" rel="stylesheet" type="text/css">'
67 }
68}
69
70fn minify_pr_files_html(mut ctx Context) bool {
71 if ctx.res.body.len == 0 {
72 return true
73 }
74 minified := strip_intertag_whitespace(ctx.res.body)
75 if minified.len != ctx.res.body.len {
76 ctx.res.body = minified
77 ctx.res.header.set(.content_length, ctx.res.body.len.str())
78 }
79 return true
80}
81
82fn strip_intertag_whitespace(s string) string {
83 mut out := []u8{cap: s.len}
84 mut i := 0
85 mut preserve_whitespace_depth := 0
86 for i < s.len {
87 ch := s[i]
88 if ch == `<` {
89 tag_end := html_tag_end(s, i)
90 if tag_end == -1 {
91 out << ch
92 i++
93 continue
94 }
95 tag_name, closing, self_closing := html_tag_info(s, i, tag_end)
96 compact_tag := compact_html_tag(s, i, tag_end)
97 for k := 0; k < compact_tag.len; k++ {
98 out << compact_tag[k]
99 }
100 if preserves_html_whitespace(tag_name) {
101 if closing {
102 if preserve_whitespace_depth > 0 {
103 preserve_whitespace_depth--
104 }
105 } else if !self_closing {
106 preserve_whitespace_depth++
107 }
108 }
109 i = tag_end + 1
110 continue
111 }
112 if is_html_space(ch) {
113 mut j := i + 1
114 mut has_indentation := ch != ` `
115 for j < s.len && is_html_space(s[j]) {
116 if s[j] != ` ` {
117 has_indentation = true
118 }
119 j++
120 }
121 prev_is_tag_end := out.len > 0 && out[out.len - 1] == `>`
122 next_is_tag_start := j < s.len && s[j] == `<`
123 should_strip := preserve_whitespace_depth == 0
124 && ((prev_is_tag_end && next_is_tag_start)
125 || (has_indentation && (prev_is_tag_end || next_is_tag_start)))
126 if should_strip {
127 i = j
128 continue
129 }
130 if preserve_whitespace_depth == 0 && has_indentation {
131 out << ` `
132 } else {
133 for k := i; k < j; k++ {
134 out << s[k]
135 }
136 }
137 i = j
138 continue
139 }
140 out << ch
141 i++
142 }
143 return out.bytestr()
144}
145
146fn compact_html_tag(s string, start int, end int) string {
147 mut out := []u8{cap: end - start + 1}
148 mut i := start
149 for i <= end {
150 ch := s[i]
151 if ch == `"` || ch == `'` {
152 quote := ch
153 out << ch
154 mut value_end := i + 1
155 for value_end <= end && s[value_end] != quote {
156 value_end++
157 }
158 if value_end <= end {
159 mut value_start := i + 1
160 mut value_finish := value_end
161 for value_start < value_finish && is_html_space(s[value_start]) {
162 value_start++
163 }
164 for value_finish > value_start && is_html_space(s[value_finish - 1]) {
165 value_finish--
166 }
167 for k := value_start; k < value_finish; k++ {
168 out << s[k]
169 }
170 out << quote
171 i = value_end + 1
172 continue
173 }
174 }
175 out << ch
176 i++
177 }
178 return out.bytestr()
179}
180
181fn html_tag_end(s string, start int) int {
182 mut quote := u8(0)
183 for i := start + 1; i < s.len; i++ {
184 ch := s[i]
185 if quote != 0 {
186 if ch == quote {
187 quote = 0
188 }
189 } else if ch == `"` || ch == `'` {
190 quote = ch
191 } else if ch == `>` {
192 return i
193 }
194 }
195 return -1
196}
197
198fn html_tag_info(s string, start int, end int) (string, bool, bool) {
199 mut i := start + 1
200 mut closing := false
201 if i < end && s[i] == `/` {
202 closing = true
203 i++
204 }
205 for i < end && is_html_space(s[i]) {
206 i++
207 }
208 name_start := i
209 for i < end && is_html_tag_name_char(s[i]) {
210 i++
211 }
212 name := s[name_start..i].to_lower()
213 mut j := end - 1
214 for j > start && is_html_space(s[j]) {
215 j--
216 }
217 self_closing := !closing && j > start && s[j] == `/`
218 return name, closing, self_closing
219}
220
221fn preserves_html_whitespace(tag_name string) bool {
222 return tag_name in ['s', 'pre', 'textarea', 'script', 'style']
223}
224
225fn is_html_tag_name_char(ch u8) bool {
226 return (ch >= `a` && ch <= `z`) || (ch >= `A` && ch <= `Z`)
227 || (ch >= `0` && ch <= `9`) || ch == `-` || ch == `_` || ch == `:`
228}
229
230fn is_html_space(ch u8) bool {
231 return ch == ` ` || ch == `\n` || ch == `\t` || ch == `\r`
232}
233