aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/File.zig
blob: e7c3b6de7edd3594f5e6f1d57ac9da4ac1658def (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
const std = @import("std");

pub fn File(comptime tag: ?[]const u8, Iterator: type) type {
    const opening = if (tag) |t| "<" ++ t ++ ">" else "";
    const closing = if (tag) |t| "</" ++ t ++ ">" else "";

    return struct {
        file: []const u8,
        do_minify: bool,

        pub fn path(comptime p: []const u8) @This() {
            return .{
                .file = p,
                .do_minify = false,
            };
        }

        pub fn minify(comptime p: []const u8) @This() {
            return .{
                .file = p,
                .do_minify = true,
            };
        }

        fn content(comptime self: @This()) []const u8 {
            return opening ++ @embedFile(self.file) ++ closing;
        }

        fn content_minified(comptime self: @This()) []const u8 {
            var minified: []const u8 = "";
            var iterator: Iterator = .init(@embedFile(self.file));

            while (iterator.next()) |segment| {
                minified = minified ++ segment;
            }

            return opening ++ minified ++ closing;
        }

        pub fn to_html_string(comptime self: @This()) []const u8 {
            return if (self.do_minify) self.content_minified() else self.content();
        }
    };
}

fn StringIterator(comptime quotes: []const u8) type {
    return struct {
        content: []const u8,

        pub fn init(content: []const u8) @This() {
            return .{ .content = content };
        }

        pub fn next(self: *@This()) ?[]const u8 {
            @setEvalBranchQuota(self.content.len * 20);

            self.content = std.mem.trimStart(u8, self.content, &std.ascii.whitespace);

            if (self.content.len == 0) return null;

            var index: usize = 0;

            while (self.content.len > index) {
                const char = self.content[index];

                if (std.mem.indexOfScalar(u8, quotes, char) != null) {
                    index += 1;
                    while (self.content.len > index) {
                        if (self.content[index] == char) {
                            index += 1;
                            break;
                        }
                        index += 1;
                    }
                } else if (std.ascii.isWhitespace(char)) {
                    break;
                }
                index += 1;
            }

            const block = self.content[0..index];
            self.content = self.content[index..];

            return block ++ " ";
        }
    };
}

pub const Style = File("style", StringIterator("\"'"));
pub const Script = File("script", StringIterator("\"'`"));
pub const Html = File(null, StringIterator("\"'"));