gitout

A static git page generator
git clone https://git.bracken.jp/gitout.git
Log | Files | Refs | Submodules | README | LICENSE

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 }