fileblob.c (2841B)
1 #include "writer/html/fileblob.h" 2 3 #include <err.h> 4 #include <libgen.h> 5 #include <limits.h> 6 #include <stdbool.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #include "format.h" 12 #include "utils.h" 13 #include "writer/html/page.h" 14 15 struct HtmlFileBlob { 16 const GitRepo* repo; 17 FILE* out; 18 HtmlPage* page; 19 }; 20 21 HtmlFileBlob* html_fileblob_create(const GitRepo* repo, const char* path) { 22 HtmlFileBlob* blob = ecalloc(1, sizeof(HtmlFileBlob)); 23 blob->repo = repo; 24 25 // Create directories. 26 char filename[PATH_MAX]; 27 if (snprintf(filename, sizeof(filename), "%s.html", path) < 0) { 28 err(1, "snprintf"); 29 } 30 char out_path[PATH_MAX]; 31 path_concat(out_path, sizeof(out_path), "file", filename); 32 char dir[PATH_MAX]; 33 estrlcpy(dir, out_path, sizeof(dir)); 34 const char* d = dirname(dir); 35 if (!d) { 36 err(1, "dirname"); 37 } 38 mkdirp(d); 39 blob->out = efopen(out_path, "w"); 40 41 // Compute the relative path. 42 char relpath[PATH_MAX]; 43 estrlcpy(relpath, "../", sizeof(relpath)); 44 for (const char* p = d; *p != '\0'; p++) { 45 if (*p == '/') { 46 estrlcat(relpath, "../", sizeof(relpath)); 47 } 48 } 49 estrlcpy(filename, path, sizeof(filename)); 50 const char* title = basename(filename); 51 if (!title) { 52 err(1, "basename"); 53 } 54 blob->page = html_page_create(blob->out, repo, title, relpath); 55 return blob; 56 } 57 58 void html_fileblob_free(HtmlFileBlob* blob) { 59 if (!blob) { 60 return; 61 } 62 fclose(blob->out); 63 blob->out = NULL; 64 html_page_free(blob->page); 65 blob->page = NULL; 66 free(blob); 67 } 68 69 void html_fileblob_begin(HtmlFileBlob* blob) { 70 html_page_begin(blob->page); 71 } 72 73 void html_fileblob_add_file(HtmlFileBlob* blob, const GitFile* file) { 74 FILE* out = blob->out; 75 76 fprintf(out, "<p> "); 77 char path[PATH_MAX]; 78 estrlcpy(path, gitfile_repo_path(file), sizeof(path)); 79 const char* filename = basename(path); 80 if (!filename) { 81 err(1, "basename"); 82 } 83 print_xml_encoded(out, filename); 84 fprintf(out, " (%zdB)", gitfile_size_bytes(file)); 85 fprintf(out, "</p><hr/>"); 86 87 if (gitfile_size_lines(file) < 0) { 88 fprintf(out, "<p>Binary file.</p>\n"); 89 return; 90 } 91 92 fprintf(out, "<pre id=\"blob\">\n"); 93 94 size_t i = 0; 95 const char* content = gitfile_content(file); 96 const char* end = content + strlen(content); 97 const char* cur_line = content; 98 while (cur_line) { 99 const char* next_line = strchr(cur_line, '\n'); 100 if (next_line || cur_line < end) { 101 size_t len = (next_line ? next_line : end) - cur_line; 102 i++; 103 fprintf(out, "<a href=\"#l%zu\" class=\"line\" id=\"l%zu\">", i, i); 104 fprintf(out, "%7zu</a> ", i); 105 print_xml_encoded_len(out, cur_line, len, false); 106 fprintf(out, "\n"); 107 } 108 cur_line = next_line ? next_line + 1 : NULL; 109 } 110 fprintf(out, "</pre>\n"); 111 } 112 113 void html_fileblob_end(HtmlFileBlob* blob) { 114 html_page_end(blob->page); 115 }