commit 1a1d986a920a2ddd56e8db4c0ed039a50e8277b5
parent deb822c63f0298af256d313754b7d81bec708ab5
Author: maydayv7 <maydayv7@gmail.com>
Date: Sun, 4 Jan 2026 00:47:25 +0530
refactor: Use `render.py`
Diffstat:
| M | README.md | | | 3 | +-- |
| M | flake.nix | | | 37 | ++++++++++++++++++++++++------------- |
| A | render.py | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | stagit.c | | | 111 | +++++++++++++++++++++++++++----------------------------------------------------- |
4 files changed, 117 insertions(+), 89 deletions(-)
diff --git a/README.md b/README.md
@@ -11,10 +11,9 @@ This is my personal [fork](https://git.codemadness.org/stagit/) of `stagit`.
- Modified styling
- Added `-n` flag to set `sitename` for header button
- Pages are now styled by the `style.css` present at root
-- Added [md4c](https://github.com/mity/md4c) to parse Markdown files
-- Added [Chroma](https://github.com/alecthomas/chroma) for code syntax highlighting
- Sort repositories by last commit time on `index` page
- Use local system timezone
+- Added code syntax highlighting and Markdown rendering using [`render.py`](./render.py)
## Usage
diff --git a/flake.nix b/flake.nix
@@ -8,35 +8,46 @@
outputs =
{ nixpkgs, utils, ... }:
utils.lib.eachDefaultSystem (
- system: with nixpkgs.legacyPackages.${system}; {
- packages.default = stdenv.mkDerivation {
+ system:
+ let
+ pkgs = nixpkgs.legacyPackages.${system};
+ pythonEnv = pkgs.python3.withPackages (
+ ps: with ps; [
+ pygments
+ markdown
+ pymdown-extensions
+ ]
+ );
+ in
+ {
+ packages.default = pkgs.stdenv.mkDerivation {
pname = "stagit";
version = "1.2-custom";
src = ./.;
-
- buildInputs = [
- libgit2
- md4c
- ];
-
+ buildInputs = [ pkgs.libgit2 ];
nativeBuildInputs = [
- pkg-config
- makeWrapper
+ pkgs.pkg-config
+ pkgs.makeWrapper
];
buildPhase = ''
make PREFIX=$out \
- STAGIT_CFLAGS="-I${libgit2}/include -I${md4c}/include" \
- STAGIT_LDFLAGS="-L${libgit2}/lib -lgit2 -L${md4c}/lib -lmd4c -lmd4c-html"
+ STAGIT_CFLAGS="-I${pkgs.libgit2}/include" \
+ STAGIT_LDFLAGS="-L${pkgs.libgit2}/lib -lgit2"
'';
installPhase = ''
mkdir -p $out/bin
mkdir -p $out/share/doc/stagit
+
cp stagit $out/bin/
cp stagit-index $out/bin/
cp favicon.png $out/share/doc/stagit/
- wrapProgram $out/bin/stagit --prefix PATH : ${lib.makeBinPath [ chroma ]}
+
+ cp render.py $out/bin/render
+ sed -i "1i #!${pythonEnv}/bin/python3" $out/bin/render
+ chmod +x $out/bin/render
+ wrapProgram $out/bin/stagit --prefix PATH : "$out/bin"
'';
};
}
diff --git a/render.py b/render.py
@@ -0,0 +1,55 @@
+import pygments
+from pygments import highlight
+from pygments.formatters import HtmlFormatter
+from pygments.lexers import guess_lexer, guess_lexer_for_filename
+from sys import stdin, stderr
+
+filename = stdin.readline().strip()
+contents = stdin.read()
+lexer = None
+
+try:
+ lexer = guess_lexer_for_filename(filename, contents)
+except pygments.util.ClassNotFound:
+ try:
+ lexer = guess_lexer(contents)
+ except pygments.util.ClassNotFound:
+ pass
+
+if lexer is None:
+ from pygments.lexers import TextLexer
+
+ lexer = TextLexer()
+
+rendered = None
+if lexer.__class__ is pygments.lexers.MarkdownLexer:
+ from markdown import markdown
+
+ rendered = markdown(
+ contents,
+ extensions=["codehilite", "extra", "sane_lists", "smarty", "pymdownx.tasklist"],
+ )
+
+FORMAT = HtmlFormatter(
+ style="murphy",
+ cssclass="highlight",
+ linenos="table",
+ lineanchors="loc",
+ anchorlinenos=True,
+ linespans="line",
+)
+
+if rendered:
+ print("<h3>Rendered</h3>")
+ print('<article class="markup markdown">')
+ print(rendered)
+ print("</article>")
+ print("<br /><h3>Code</h3>")
+
+print('<div id="blob">')
+print(highlight(contents, lexer, FORMAT))
+print("</div>")
+
+print("Filename: {}; Lexer: {}.".format(filename, lexer), file=stderr)
+if rendered:
+ print("Markdown was rendered in addition.", file=stderr)
diff --git a/stagit.c b/stagit.c
@@ -16,7 +16,6 @@
#include "compat.h"
-#include <md4c-html.h>
#define CMD_BUFSIZE 255
#define LEN(s) (sizeof(s) / sizeof(*s))
@@ -533,7 +532,7 @@ void writeheader(FILE *fp, const char *title) {
fputs("</div>\n", fp);
fputs("</div>\n", fp);
- fputs("<nav class=\"menu-desktop\">\n", fp);
+ fputs("<nav class=\"menu\">\n", fp);
fputs("<ul class=\"menu-inner\">\n", fp);
fprintf(fp, "<li><a href=\"%slog.html\">Log</a></li>", relpath);
@@ -587,92 +586,58 @@ const char *get_ext(const char *filename) {
return dot + 1;
}
-void processmd(const char *output, unsigned int len, void *fp) {
- fprintf((FILE *)fp, "%.*s", len, output);
-}
-
-size_t writeblobmd(FILE *fp, const git_blob *blob) {
- size_t n = 0, i, len, prev, ret;
- const char *s = git_blob_rawcontent(blob);
- len = git_blob_rawsize(blob);
- fputs("<div id=\"md\">\n", fp);
+int custom_render(const char *filename, FILE *fp, const char *s, size_t len) {
+ fflush(fp);
- if (len > 0) {
- for (i = 0, prev = 0; i < len; i++) {
- if (s[i] != '\n')
- continue;
- n++;
- prev = i + 1;
- }
- if ((len - prev) > 0)
- n++;
-
- ret = md_html(s, len, processmd, fp,
- MD_FLAG_TABLES | MD_FLAG_TASKLISTS |
- MD_FLAG_PERMISSIVEEMAILAUTOLINKS |
- MD_FLAG_PERMISSIVEURLAUTOLINKS,
- 0);
+ int stdout_copy = dup(1);
+ if (stdout_copy == -1) {
+ fprintf(stderr, "Error duplicating stdout: %s\n", strerror(errno));
+ return 0;
}
- fputs("</div>\n", fp);
- return n;
-}
-size_t writeblobhtml(const char *filename, FILE *fp, const git_blob *blob) {
- char *line = NULL;
- size_t linesize = 0;
- ssize_t linelen;
- int lineno = 1;
- char tmp_path[] = "/tmp/stagit-blob-XXXXXX";
- int fd;
- FILE *chroma_out;
- char cmd[1024];
-
- const char *content = git_blob_rawcontent(blob);
- size_t content_len = git_blob_rawsize(blob);
-
- if ((fd = mkstemp(tmp_path)) == -1) {
- fprintf(stderr, "stagit: mkstemp failed\n");
+ if (dup2(fileno(fp), 1) == -1) {
+ fprintf(stderr, "Error redirecting stdout: %s\n", strerror(errno));
+ close(stdout_copy);
return 0;
}
- if (write(fd, content, content_len) == -1) {
- fprintf(stderr, "stagit: write to temp failed\n");
- close(fd);
- unlink(tmp_path);
+
+ FILE *child = popen("render", "w");
+ if (child == NULL) {
+ dup2(stdout_copy, 1);
+ close(stdout_copy);
+ fprintf(stderr, "popen('render') failed: %s\n", strerror(errno));
return 0;
}
- close(fd);
- snprintf(cmd, sizeof(cmd),
- "chroma --html --html-only --html-prevent-surrounding-pre "
- "--filename '%s' %s",
- filename, tmp_path);
+ fprintf(child, "%s\n", filename);
- chroma_out = popen(cmd, "r");
- if (!chroma_out) {
- unlink(tmp_path);
- return 0;
+ size_t i;
+ int lc = 0;
+ for (i = 0; *s && i < len; s++, i++) {
+ if (*s == '\n')
+ lc++;
+ fputc(*s, child);
}
- fputs("<table id=\"blob\" class=\"chroma\"><tbody>\n", fp);
+ pclose(child);
- while ((linelen = getline(&line, &linesize, chroma_out)) != -1) {
- if (line[linelen - 1] == '\n')
- line[linelen - 1] = '\0';
+ fflush(stdout);
- fprintf(fp,
- "<tr><td class=\"num\"><a href=\"#l%d\" id=\"l%d\">%d</a></td>"
- "<td class=\"code\">%s</td></tr>\n",
- lineno, lineno, lineno, line);
- lineno++;
- }
+ dup2(stdout_copy, 1);
+ close(stdout_copy);
- fputs("</tbody></table>\n", fp);
+ return lc;
+}
+
+int writeblobhtml(const char *filename, FILE *fp, const git_blob *blob) {
+ int lc = 0;
+ const char *s = git_blob_rawcontent(blob);
+ git_off_t len = git_blob_rawsize(blob);
- free(line);
- pclose(chroma_out);
- unlink(tmp_path);
+ if (len > 0)
+ lc = custom_render(filename, fp, s, len);
- return lineno - 1;
+ return lc;
}
void printcommit(FILE *fp, struct commitinfo *ci) {
@@ -1070,8 +1035,6 @@ size_t writeblob(git_object *obj, const char *fpath, const char *filename,
if (git_blob_is_binary((git_blob *)obj))
fputs("<p>Binary file.</p>\n", fp);
- else if (git_blob_is_markdown_file(filename))
- lc = writeblobmd(fp, (git_blob *)obj);
else
lc = writeblobhtml(filename, fp, (git_blob *)obj);