mobley

C Git HTTP server
Log | Files | Refs | Submodules | README | git clone https://git.ne02ptzero.me/git/mobley

commit 2f675489c2084fe4a145045bc165e0a868e743b1
parent d89fc1df0c7f983ba7537ae07df02250bacd87fe
Author: Louis Solofrizzo <lsolofrizzo@online.net>
Date:   Fri, 28 Dec 2018 16:53:14 +0100

Add code file syntax highlighting with lib-source-highlight

Signed-off-by: Louis Solofrizzo <lsolofrizzo@online.net>

Diffstat:
MCMakeLists.txt | 4+++-
MREADME.md | 1+
Mconfig.c | 2++
Mconfig.yaml | 5+++--
Mfile.c | 44+++++++++++++++++++++++++++++++++++++++++++-
Mfile_format.c | 3++-
Mmobley.h | 2++
Mstyle/main.css | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Awatm/CMakeLists.txt | 5+++++
Awatm/shl-wrapper-lib.cpp | 48++++++++++++++++++++++++++++++++++++++++++++++++
Awatm/shl-wrapper.h | 31+++++++++++++++++++++++++++++++
11 files changed, 227 insertions(+), 6 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -39,7 +39,9 @@ include_directories(".") include_directories("./contrib/sundown/src") include_directories("./contrib/sundown") -link_libraries(pthread event event_openssl crypto ssl evhtp yaml git2) +add_subdirectory("./watm") + +link_libraries(pthread event event_openssl crypto ssl evhtp yaml git2 shl-wrapper) add_executable(${MOBLEY_NAME} main.c args.c diff --git a/README.md b/README.md @@ -5,6 +5,7 @@ HTTP Git C Server # Dependencies - libevhtp-git +- source-highlight # Build ``` diff --git a/config.c b/config.c @@ -61,6 +61,8 @@ static bool config_read_token(const char *tok, unsigned char *value, mobley_t *c } else if (strcmp(tok, "clone_ssh_url") == 0) COPY_OR_FAIL(ctx->conf.clone_ssh_url, value); + else if (strcmp(tok, "source_highlight_data_dir") == 0) + COPY_OR_FAIL(ctx->conf.source_highlight_data_dir, value); else { printf("Unknown token = %s\n", tok); diff --git a/config.yaml b/config.yaml @@ -1,4 +1,4 @@ -address : 127.0.0.1 +address : 192.168.1.215 port : 4242 static_dir : /usr/local/share/mobley logo : logo.png @@ -7,6 +7,7 @@ title : git:// repo_dir : /home/louis/Work/perso/git_local/repositories sort_repo : true clone_ssh_url : git@git.ne02ptzero.me +source_highlight_data_dir : /usr/share/source-highlight/ styles: - main.css @@ -64,7 +65,7 @@ repositories: owner : louis - dir : ne02ptzero.me.git - name : ne2ptzero.me + name : ne02ptzero.me description : my personnal website owner : louis diff --git a/file.c b/file.c @@ -17,6 +17,8 @@ #include <file_format.h> #include <html.h> +#include <watm/shl-wrapper.h> + static bool file_show_markdown(mobley_t *ctx, server_req_t *r, git_blob *blob) { struct buf *ob = bufnew(4096); @@ -52,6 +54,45 @@ static bool file_show_image(mobley_t *ctx, server_req_t *r, const char *path) return true; } +# define TEMPLATE_NAME "/tmp/mobley_tmp_XXXXXX" +static bool file_show_code(mobley_t *ctx, server_req_t *r, const char *path, git_blob *blob) +{ + source_highlight_init(ctx->conf.source_highlight_data_dir, "htmlcss.outlang", path); + char *in = mkdtemp(strdup(TEMPLATE_NAME)); + char *out = mkdtemp(strdup(TEMPLATE_NAME)); + char __path_in[PATH_MAX] = { 0 }; + char __path_out[PATH_MAX] = { 0 }; + int fd_in = -1; + int fd_out; + struct stat st; + + snprintf(__path_in, sizeof(__path_in), "%s/file", in); + snprintf(__path_out, sizeof(__path_out), "%s/file", out); + + fd_in = open(__path_in, O_WRONLY | O_CREAT, 0777); + write(fd_in, git_blob_rawcontent(blob), git_blob_rawsize(blob)); + close(fd_in); + + source_highlight_file(__path_in, __path_out); + source_highlight_cleanup(); + + fd_out = open(__path_out, O_RDONLY); + fstat(fd_out, &st); + + evbuffer_add_file(r->req->buffer_out, fd_out, 0, st.st_size); + close(fd_out); + + unlink(__path_in); + // Keep this as cache + unlink(__path_out); + rmdir(in); + rmdir(out); + free(in); + free(out); + + return true; +} + static bool file_show_header(mobley_t *ctx, server_req_t *r, git_blob *blob, const char *path) { html_open("table", .class = "file-header") { @@ -92,11 +133,12 @@ bool file_show(mobley_t *ctx, server_req_t *r, git_tree_entry *entry, bool heade ret = file_show_markdown(ctx, r, (git_blob *)obj); else if (file_is_image(path)) ret = file_show_image(ctx, r, r->path); + else if (file_is_code(path)) + ret = file_show_code(ctx, r, r->path, (git_blob *)obj); else ret = file_show_raw(ctx, r, (git_blob *)obj); } html_close("div"); git_object_free(obj); - git_tree_entry_free(entry); return ret; } diff --git a/file_format.c b/file_format.c @@ -59,7 +59,8 @@ bool file_is_code(const char *filename) { const char *formats[] = { ".c", ".cpp", ".h", ".hpp", ".cxx", ".cc", - ".js", ".html", ".css", ".py", ".php" // XXX + ".js", ".html", ".css", ".py", ".php", ".tex", + ".json", ".bash", ".sh", ".zsh", ".xml" }; return format_match(formats, COUNT_OF(formats), filename); diff --git a/mobley.h b/mobley.h @@ -37,6 +37,7 @@ typedef struct { char *title; bool sort_repo; char *clone_ssh_url; + char *source_highlight_data_dir; list_head_t styles; } conf; @@ -62,6 +63,7 @@ static inline void mobley_conf_dtr(mobley_t *ctx) free(ctx->conf.title); free(ctx->repos.repo_dir); free(ctx->conf.clone_ssh_url); + free(ctx->conf.source_highlight_data_dir); string_array_free(&ctx->conf.styles); repository_list_free(&ctx->repos.repos); } diff --git a/style/main.css b/style/main.css @@ -139,7 +139,7 @@ table tbody .commit a { color: #999; } -.url { +li .url { padding: 1px 8px; color: white; background: black; @@ -194,3 +194,89 @@ table tbody .commit a { margin-top: 10px; background-image: url("data:image/gif;base64,R0lGODlhCgAKAIAAABoaGgAAACwAAAAACgAKAAACEYQdmYcaDNxjEspKndVZbc8UADs="); } + +/* Code highlight */ + +.file-content pre { + background-color: #101010; + color: #ffffff; + border: 0; + font-size: .85em; + margin-left: -10px; +} + + +.file-content pre a:hover { + text-decoration: none; +} + +.file-content pre a span { + display: inline-block; + width: 40px; + text-align: right; +} + +.file-content pre a span:hover { + text-decoration: underline; + color: white; +} + +.keyword { + color: #8197bf; + font-weight: normal; + font-style: normal; +} + +.type { + color: #ffed8a; + font-weight: normal; + font-style: normal; +} + +.string { + color: #99ad6a; + font-weight: normal; + font-style: normal; +} + +.specialchar { + color: #799d6a; + font-weight: normal; + font-style: normal; +} + +.comment { + color: #888888; + font-weight: normal; + font-style: italic; +} + +.number { + color: #cf6a4c; + font-weight: normal; + font-style: normal; +} + +.preproc { + color: #8fbfdc; + font-weight: normal; + font-style: normal; +} + +.symbol { + color: #ababab; + font-weight: normal; + font-style: normal; +} + +.function { + color: #ffffff; + font-weight: normal; + font-style: normal; +} + +.cbracket { + color: #ababab; + font-weight: normal; + font-style: normal; +} diff --git a/watm/CMakeLists.txt b/watm/CMakeLists.txt @@ -0,0 +1,5 @@ +add_library(shl-wrapper STATIC + shl-wrapper-lib.cpp +) + +target_link_libraries(shl-wrapper PUBLIC source-highlight) diff --git a/watm/shl-wrapper-lib.cpp b/watm/shl-wrapper-lib.cpp @@ -0,0 +1,48 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <srchilite/sourcehighlight.h> +#include <srchilite/langmap.h> + +static srchilite::SourceHighlight *ctx = NULL; +static std::string lang; + +extern "C" bool source_highlight_init(const char *data_dir, const char *outlang, const char *fn) +{ + srchilite::LangMap langMap(data_dir, "lang.map"); + + lang = langMap.getMappedFileNameFromFileName(fn); + ctx = new srchilite::SourceHighlight("htmlcss.outlang"); + if (ctx == NULL) + return false; + + ctx->setDataDir(data_dir); + ctx->setGenerateLineNumbers(true); + ctx->setGenerateLineNumberRefs(true); + ctx->setLineNumberPad(0); + return true; +} + +extern "C" void source_highlight_cleanup(void) +{ + lang = ""; + delete ctx; +} + +extern "C" bool source_highlight_file(const char *in, const char *out) +{ + ctx->highlight(in, out, lang); + return true; +} diff --git a/watm/shl-wrapper.h b/watm/shl-wrapper.h @@ -0,0 +1,31 @@ +/** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +#ifndef SHL_WRAPPER_H +# define SHL_WRAPPER_H + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + +bool source_highlight_init(const char *data_dir, const char *outlang, const char *fn); +void source_highlight_cleanup(void); +bool source_highlight_file(const char *in, const char *out); + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + +#endif /* SHL_WRAPPER_H */