diff options
-rw-r--r-- | Makefile | 30 | ||||
-rw-r--r-- | README.md | 10 | ||||
-rw-r--r-- | assets/templates/album.html | 2 | ||||
-rw-r--r-- | assets/templates/base.html | 6 | ||||
-rw-r--r-- | assets/templates/index.html | 31 | ||||
-rw-r--r-- | docs/revela.1.scd | 65 | ||||
-rw-r--r-- | docs/revela.5.scd | 90 | ||||
-rw-r--r-- | include/config.h | 1 | ||||
-rw-r--r-- | include/site.h | 2 | ||||
m--------- | roscha | 0 | ||||
-rw-r--r-- | src/components.c | 4 | ||||
-rw-r--r-- | src/config.c | 7 | ||||
-rw-r--r-- | src/revela.c | 24 | ||||
-rw-r--r-- | src/site.c | 5 | ||||
-rw-r--r-- | src/tests/config.c | 1 | ||||
-rw-r--r-- | tests/site.ini | 1 | ||||
-rwxr-xr-x | util/revela-init | 30 |
17 files changed, 258 insertions, 51 deletions
@@ -27,7 +27,9 @@ REVELA_OBJS:=$(REVELA_SRCS:%.c=$(OBJDIR)/%.o) ALL_OBJS:=$(ROSCHA_OBJS) $(PARCINI_OBJS) $(REVELA_OBJS) TEST_OBJS:=$(filter-out $(OBJDIR)/src/revela.o,$(ALL_OBJS)) -all: revela +PREFIX?=/usr/local/ + +all: revela docs test: tests/config tests/fs @@ -43,9 +45,33 @@ revela: $(ALL_OBJS) mkdir -p $(@D) $(CC) -o $(BUILDIR)/$@ $^ $(LIBS) $(CFLAGS) +docs: + mkdir -p build/man/ + scdoc < docs/revela.1.scd > build/man/revela.1 + scdoc < docs/revela.5.scd > build/man/revela.5 + +install: + mkdir -p $(PREFIX)/bin + mkdir -p $(PREFIX)/share/man/man1 + mkdir -p $(PREFIX)/share/man/man5 + mkdir -p $(PREFIX)/share/revela + install -m755 $(BUILDIR)/revela $(PREFIX)/bin/revela + install -m755 util/revela-init $(PREFIX)/share/revela/revela-init + ln -sf $(PREFIX)/share/revela/revela-init $(PREFIX)/bin/ + install -m644 build/man/revela.1 $(PREFIX)/share/man/man1/revela.1 + install -m644 build/man/revela.5 $(PREFIX)/share/man/man5/revela.5 + cp -r assets $(PREFIX)/share/revela/ + +uninstall: + rm -rf $(PREFIX)/share/revela + rm -f $(PREFIX)/bin/revela + rm -f $(PREFIX)/bin/revela-init + rm -f $(PREFIX)/share/man/man1/revela.1 + rm -f $(PREFIX)/share/man/man5/revela.5 + clean: rm -r build -.PHONY: clean all test +.PHONY: clean all test docs install uninstall .PRECIOUS: $(OBJDIR)/src/tests/%.o @@ -4,8 +4,6 @@ A static web image gallery generator. It optimizes images for the web and generates HTML files to create a photo/image gallery web site ready to be served by an HTML server. -Alpha stages. It's functional but a little rough around the edges. - ## Building revela depends on GraphicsMagick (1.3+ tested) and libexif (0.6+ tested). @@ -21,11 +19,13 @@ or for debugging: DEBUG=1 make ``` +## Usage + +For information on how to use revela, consult `man revela` if installed on your +system, or read the contents in `docs/` in the source. + ## TODO: * Add exif tags to template hashmap. -* Improve unja or find better alternative. -* Get rid of previews variable. It is a temporary hack to limit the amount of - thumbnails for each album in the index. * Better test coverage? (if I am not too lazy) * Document. diff --git a/assets/templates/album.html b/assets/templates/album.html index 95d9935..856cf63 100644 --- a/assets/templates/album.html +++ b/assets/templates/album.html @@ -12,7 +12,9 @@ <p>from <a href="{{ index }}/">{{ title }}</a> </p> </div> <div class="gallery-container"> + {% if album.desc %} <p>{{ album.desc }}</p> + {% endif %} <div class="album-container"> {% for thumb in album.thumbs %} <a href="{{ thumb.link }}"> diff --git a/assets/templates/base.html b/assets/templates/base.html index 1f2d8dc..11ba0ab 100644 --- a/assets/templates/base.html +++ b/assets/templates/base.html @@ -3,11 +3,7 @@ <head> <meta charset="utf-8"> <meta content="width=device-width, initial-scale=1" name="viewport"> - <title> - {% block title %} - A photo gallery by Yaroslav de la Peña Smirnov - {% endblock %} - </title> + <title>{% block title %}{{ title }}{% endblock %}</title> <link rel="stylesheet" href="{{ index }}/css/gallery.css"> </head> <body> diff --git a/assets/templates/index.html b/assets/templates/index.html index 61160a5..bf62607 100644 --- a/assets/templates/index.html +++ b/assets/templates/index.html @@ -11,23 +11,24 @@ {% endfor %} </p> {% for year in years %} - <h2 id="{{ year.name }}">{{ year.name }}</h2> - {% for album in year.albums %} - {% if album.title %} - <a href="{{ album.link }}"><h3>{{ album.title }}</h3></a> - {% else %} - <a href="{{ album.link }}"><h3>Untitled</h3></a> - {% endif %} - <div class="album-container"> - {% for thumb in album.thumbs %} - {% if loop.index < 4 %} - <a href="{{ thumb.link }}"> - <img class="thumbnail" src="{{ thumb.source }}"> - </a> + <h2 id="{{ year.name }}">{{ year.name }}</h2> + {% for album in year.albums %} + {% if album.title %} + <a href="{{ album.link }}"><h3>{{ album.title }}</h3></a> + {% else %} + <a href="{{ album.link }}"><h3>Untitled</h3></a> {% endif %} + <div class="album-container"> + {% for thumb in album.thumbs %} + {% if loop.index >= 4 %} + {% break %} + {% endif %} + <a href="{{ thumb.link }}"> + <img class="thumbnail" src="{{ thumb.source }}"> + </a> + {% endfor %} + </div> {% endfor %} - </div> - {% endfor %} {% endfor %} </div> {% endblock %} diff --git a/docs/revela.1.scd b/docs/revela.1.scd new file mode 100644 index 0000000..a503668 --- /dev/null +++ b/docs/revela.1.scd @@ -0,0 +1,65 @@ +revela(1) + +# NAME + +revela - static image gallery generator. + +# SYNOPSIS + +*revela* [_OPTIONS_] <_-o OUTPUT DIR_> +*revela-init* + +# DESCRIPTION + +*revela* is a static web image gallery generator. It optimizes images for the web +and generates HTML files to create a photo/image gallery web site ready to be +served by an HTML server. + +revela takes a directory with pictures, jinja-like templates and converts that +into a static web gallery of said pictures organized into albums. + +The root of the input directory should contain at least the following +directories and files: + +*content* - The directory with subdirectories that each contain pictures. Each +subdirectory with pictures is considered an album. Each album should contain an +album.ini file, for information on the format of this file read revela(5). + +*static* - Directory with 'static' directories and files to be copied as-is to the +root of the output directory. Here you can put any static assets such as +favicons, css, etc. + +*templates* - Here should go the templates for the website. There should be at +least three files: _index.html_, _image.html_ and _album.html_. There can also +be parent templates used by any of those three templates. + +*site.ini* - The configuration for the site, such as title, base url and image +optimizations. For more information consult revela(5). + +*revela-init* is an interactive helper script that generates a _site.ini_ file +and copies the default templates provided with revela in the working directory +from where it was called. + +# OPTIONS + +*-i* _DIRECTORY_ + Indicate the input directory. If not indicated it will default to the + current working dir. + +*-o* _DIRECTORY_ + The output directory. This is the only required flag. + +*-n* + Dry run. Show which files would be copied and which html files rendered but + don't do anything. + +*-V* + Prints version information and exits. + +# SEE ALSO + +*revela*(5) + +# AUTHORS + +Yaroslav de la Peña Smirnov <yps@yaroslavps.com>. diff --git a/docs/revela.5.scd b/docs/revela.5.scd new file mode 100644 index 0000000..b4656fa --- /dev/null +++ b/docs/revela.5.scd @@ -0,0 +1,90 @@ +revela(5) + +# NAME + +revela - static image gallery generator. + +# DESCRIPTION + +This manual page documents the format and syntax of the _\*.ini_ or configuration +files found in revela source galleries. + +# PREAMBLE + +There are two kinds of configuration files: + +*site.ini* - There is only one _site.ini_ file in a revela gallery and it should +be located at the root of the gallery directory. This file contains the title of +the gallery, the base url, and image optimization settings. + +*album.ini* - Each album should contain a file with this name. This simply +contains the title of the album and optionally a description. + +# SYNTAX + +Both files are in what's called 'ini format'. It merely consists of _key=value_ +pairs and _[sections]_. You should already be familiar with it. + +## SITE CONFIGURATION + +_site.ini_ may contain the following sections and keys: + +*title*=string + The name or title of the gallery to be used inside templates. + +*base_url*=string + The base url. For example, if the web gallery is not at the root of the + website, it could be "/photos". _Optional_. + +*[images]* + This section contains settings for optimization of the main image files. + _This section and all its keys are optional_. + + *strip*=boolean + Whether to strip images of their EXIF tags and other metainformation. + + *quality*=integer + From 0 to 100, 0 being the lowest quality and highest compression, and + 100 being the highest quality but no compression. This corresponds to + JPEG "quality" levels. + + *max_width*=integer + The maximum width the image file should have in pixels. + + *max_height*=integer + The maximum height the image file should have in pixels. + + *smart_resize*=boolean + Whether to preserve the aspect ratio of the image when resizing. + + *blur*=integer + A value from 0 to 100, where 0 is no blur and 100 is the maximum amount + of blur. + +*[thumbnails]* + This section contains settings for optimization of the thumbnails files of + images. All of the keys in this section are the same as in the _images_ + sections. _This section and all its keys are optional_. + +## ALBUM CONFIGURATION + +_album.ini_ may contain the following keys: + +*title*=string + The name of the album. + +*desc*=string + A short description of the album. _Optional_. + +# NOTES + +If you initialize your gallery with the helper script _revela-init_ a _site.ini_ +should be generated. You can tweak the settings by using it as a basis. + +# SEE ALSO + +*revela*(1) + +# AUTHORS + +Yaroslav de la Peña Smirnov <yps@yaroslavps.com>. diff --git a/include/config.h b/include/config.h index 589671f..085eb5e 100644 --- a/include/config.h +++ b/include/config.h @@ -19,7 +19,6 @@ struct image_config { struct site_config { char *title; char *base_url; - uint32_t max_previews; struct image_config images; struct image_config thumbnails; }; diff --git a/include/site.h b/include/site.h index e054730..43a20d2 100644 --- a/include/site.h +++ b/include/site.h @@ -21,7 +21,7 @@ struct site { struct site_config *config; MagickWand *wand; char *root_dir; - const char *output_dir; + char *output_dir; char *content_dir; /* * Indicates how many characters after the full root dir path of the input diff --git a/roscha b/roscha -Subproject 5725085e3be9ee005c9b9cc4623d5ad5f90418f +Subproject 4665a620775da64ec7280762979a9fc6fa37c0b diff --git a/src/components.c b/src/components.c index fc3bab5..aeb14b1 100644 --- a/src/components.c +++ b/src/components.c @@ -167,8 +167,8 @@ image_new(char *src, const struct stat *pstat, struct album *album) image->exif_data = exif_data_new_from_file(image->source); image->modtime = pstat->st_mtim; image_set_date(image, pstat); - image->map = roscha_object_new(hmap_new_with_cap(8)); - image->thumb = roscha_object_new(hmap_new_with_cap(4)); + image->map = roscha_object_new(hmap_new_with_cap(16)); + image->thumb = roscha_object_new(hmap_new_with_cap(8)); image->modified = false; return image; diff --git a/src/config.c b/src/config.c index 1bc531f..a570104 100644 --- a/src/config.c +++ b/src/config.c @@ -126,12 +126,6 @@ site_config_keyvalue_handler(struct parcini_line *parsed, void *dst) &config->base_url)? KV_HANDLER_OK : KV_HANDLER_BADVALUE; } - if (MATCHSK("", "max_previews", parsed)) { - return parcini_value_handle(&parsed->value, PARCINI_VALUE_INTEGER, - &config->max_previews)? - KV_HANDLER_OK : KV_HANDLER_BADVALUE; - } - out: return KV_HANDLER_NOMATCH; @@ -232,7 +226,6 @@ site_config_init(void) { struct site_config *config = calloc(1, sizeof *config); if (config != NULL) { - config->max_previews = 10; config->images = (struct image_config) { .strip = true, .quality = 80, diff --git a/src/revela.c b/src/revela.c index 32867c6..e21ae02 100644 --- a/src/revela.c +++ b/src/revela.c @@ -10,13 +10,18 @@ #include "config.h" #include "bstree.h" +#ifndef VERSION +#define VERSION "0.1.0" +#endif + static const char *usage = - "Usage: %s [options] [-i <input dir>] -o <output dir>\n"; + "Usage: %s [OPTIONS] -o <output dir>\n" + "For more information consult `man 1 revela`\n"; static struct site site = {0}; static enum log_level loglvl = LOG_DETAIL; -static void +static inline void bad_arguments(const char *cmd) { fprintf(stderr, usage, cmd); @@ -28,17 +33,23 @@ parse_arguments(int argc, char *argv[]) { int opt; char *cmd = argv[0]; - while ((opt = getopt(argc, argv, "i:o:n")) != -1) { + while ((opt = getopt(argc, argv, "i:o:nhV")) != -1) { switch (opt) { case 'i': site.root_dir = strdup(optarg); break; case 'o': - site.output_dir = optarg; + site.output_dir = realpath(optarg, NULL); break; case 'n': site.dry_run = true; break; + case 'h': + printf(usage, cmd); + exit(0); + case 'V': + printf("revela "VERSION"\n"); + exit(0); default: bad_arguments(cmd); } @@ -51,8 +62,6 @@ parse_arguments(int argc, char *argv[]) int main(int argc, char *argv[]) { - int ret = EXIT_SUCCESS; - parse_arguments(argc, argv); #ifdef DEBUG @@ -61,7 +70,7 @@ main(int argc, char *argv[]) log_set_verbosity(loglvl); #endif - ret = site_init(&site) && site_load(&site) && site_build(&site) + int ret = site_init(&site) && site_load(&site) && site_build(&site) ? EXIT_SUCCESS : EXIT_FAILURE; if (site.dry_run) { @@ -69,5 +78,6 @@ main(int argc, char *argv[]) } site_deinit(&site); + return ret; } @@ -86,10 +86,6 @@ optimize_image(MagickWand *wand, const char *dst, const struct image_config *conf, const struct timespec *srcmtim, bool dry) { - int update = file_is_uptodate(dst, srcmtim); - if (update == -1) return false; - if (update == 1) return true; - log_printl(LOG_DETAIL, "Converting %s", dst); if (dry) goto out; @@ -413,6 +409,7 @@ site_deinit(struct site *site) site_config_destroy(site->config); free(site->content_dir); free(site->root_dir); + free(site->output_dir); if (site->wand != NULL) { DestroyMagickWand(site->wand); DestroyMagick(); diff --git a/src/tests/config.c b/src/tests/config.c index 64a4da8..79e5358 100644 --- a/src/tests/config.c +++ b/src/tests/config.c @@ -15,7 +15,6 @@ test_site_config_read_ini(void) asserteq(site_config_read_ini(TESTS_DIR, config), true); asserteq(strcmp(config->title, "An example gallery"), 0); asserteq(strcmp(config->base_url, "http://www.example.com/photos"), 0); - asserteq(config->max_previews, 20); asserteq(config->images.strip, false); asserteq(config->images.quality, 80); asserteq(config->images.max_width, 3000); diff --git a/tests/site.ini b/tests/site.ini index ad4a575..f33a336 100644 --- a/tests/site.ini +++ b/tests/site.ini @@ -1,6 +1,5 @@ title = "An example gallery" base_url = "http://www.example.com/photos" -max_previews = 20 [images] strip = no diff --git a/util/revela-init b/util/revela-init new file mode 100755 index 0000000..25e3ddc --- /dev/null +++ b/util/revela-init @@ -0,0 +1,30 @@ +#!/bin/sh + +this="$(readlink -f $0)" +sharedir="$(dirname $this)" + +printf "Enter your gallery name (e.g. \"Gallery\")> " +read name +printf "Enter base url (e.g. \"/photos\"; can be empty)> " +read burl + +echo "title = \"$name\" +base_url = \"$burl\" + +[images] +strip = no +quality = 80 +max_width = 1200 +max_height = 1200 +smart_resize = yes + +[thumbnails] +strip = yes +quality = 60 +max_width = 200 +max_height = 200 +smart_resize = yes +blur = 50" > site.ini + +cp -r "$sharedir"/assets/* . +mkdir content |